Merge ../torvalds-2.6/
authorGreg KH <gregkh@suse.de>
Mon, 12 Sep 2005 19:10:59 +0000 (12:10 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 12 Sep 2005 19:10:59 +0000 (12:10 -0700)
1124 files changed:
COPYING
Documentation/00-INDEX
Documentation/CodingStyle
Documentation/DMA-API.txt
Documentation/DMA-ISA-LPC.txt [new file with mode: 0644]
Documentation/DocBook/journal-api.tmpl
Documentation/DocBook/kernel-hacking.tmpl
Documentation/DocBook/usb.tmpl
Documentation/MSI-HOWTO.txt
Documentation/RCU/RTFP.txt
Documentation/RCU/UP.txt
Documentation/RCU/checklist.txt
Documentation/RCU/rcu.txt
Documentation/RCU/rcuref.txt [new file with mode: 0644]
Documentation/RCU/whatisRCU.txt [new file with mode: 0644]
Documentation/applying-patches.txt [new file with mode: 0644]
Documentation/cpu-freq/cpufreq-stats.txt
Documentation/cpusets.txt
Documentation/crypto/descore-readme.txt
Documentation/dvb/bt8xx.txt
Documentation/dvb/ci.txt
Documentation/fb/cyblafb/bugs [new file with mode: 0644]
Documentation/fb/cyblafb/credits [new file with mode: 0644]
Documentation/fb/cyblafb/documentation [new file with mode: 0644]
Documentation/fb/cyblafb/fb.modes [new file with mode: 0644]
Documentation/fb/cyblafb/performance [new file with mode: 0644]
Documentation/fb/cyblafb/todo [new file with mode: 0644]
Documentation/fb/cyblafb/usage [new file with mode: 0644]
Documentation/fb/cyblafb/whycyblafb [new file with mode: 0644]
Documentation/fb/intel810.txt
Documentation/fb/modedb.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/files.txt [new file with mode: 0644]
Documentation/filesystems/fuse.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/filesystems/v9fs.txt [new file with mode: 0644]
Documentation/filesystems/vfs.txt
Documentation/ioctl/cdrom.txt
Documentation/kbuild/makefiles.txt
Documentation/kdump/kdump.txt
Documentation/kernel-parameters.txt
Documentation/mono.txt
Documentation/networking/bonding.txt
Documentation/networking/wan-router.txt
Documentation/pci.txt
Documentation/powerpc/eeh-pci-error-recovery.txt
Documentation/s390/s390dbf.txt
Documentation/scsi/ibmmca.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sparse.txt
Documentation/sysrq.txt
Documentation/uml/UserModeLinux-HOWTO.txt
Documentation/usb/gadget_serial.txt
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CARDLIST.tuner
Documentation/video4linux/Zoran
Documentation/x86_64/boot-options.txt
Kbuild [new file with mode: 0644]
MAINTAINERS
Makefile
REPORTING-BUGS
arch/alpha/Makefile
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/head.S
arch/alpha/kernel/module.c
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/smp.c
arch/alpha/lib/dbg_stackcheck.S
arch/alpha/lib/dbg_stackkill.S
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/common/scoop.c
arch/arm/kernel/calls.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/entry-header.S
arch/arm/kernel/head.S
arch/arm/kernel/iwmmxt.S
arch/arm/lib/copy_page.S
arch/arm/lib/csumpartialcopyuser.S
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/corgi_ssp.c
arch/arm/mach-s3c2410/devs.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mm/copypage-v3.S
arch/arm/mm/copypage-v4wb.S
arch/arm/mm/copypage-v4wt.S
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm6_7.S
arch/arm/mm/proc-arm720.S
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-sa110.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-v6.S
arch/arm/mm/tlb-v3.S
arch/arm/mm/tlb-v4.S
arch/arm/mm/tlb-v4wb.S
arch/arm/mm/tlb-v4wbi.S
arch/arm/mm/tlb-v6.S
arch/arm/nwfpe/entry26.S
arch/arm/vfp/entry.S
arch/arm26/Makefile
arch/arm26/kernel/entry.S
arch/arm26/lib/copy_page.S
arch/arm26/lib/csumpartialcopyuser.S
arch/arm26/lib/getuser.S
arch/arm26/lib/putuser.S
arch/arm26/mm/proc-funcs.S
arch/arm26/nwfpe/entry.S
arch/cris/Makefile
arch/cris/arch-v10/kernel/entry.S
arch/cris/arch-v32/kernel/entry.S
arch/frv/kernel/asm-offsets.c [new file with mode: 0644]
arch/h8300/Makefile
arch/i386/Makefile
arch/i386/boot/video.S
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/acpi/wakeup.S
arch/i386/kernel/cpu/common.c
arch/i386/kernel/entry.S
arch/i386/kernel/head.S
arch/i386/kernel/io_apic.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/setup.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/srat.c
arch/i386/kernel/time.c
arch/i386/kernel/vmlinux.lds.S
arch/i386/kernel/vsyscall-sigreturn.S
arch/i386/kernel/vsyscall.lds.S
arch/i386/pci/acpi.c
arch/i386/pci/mmconfig.c
arch/i386/power/swsusp.S
arch/ia64/Makefile
arch/ia64/hp/sim/boot/boot_head.S
arch/ia64/ia32/ia32_entry.S
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/fsys.S
arch/ia64/kernel/gate.S
arch/ia64/kernel/head.S
arch/ia64/kernel/ivt.S
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/minstate.h
arch/ia64/kernel/palinfo.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/unwind.c
arch/ia64/mm/init.c
arch/ia64/sn/kernel/setup.c
arch/ia64/sn/kernel/xpnet.c
arch/m32r/Kconfig
arch/m32r/kernel/asm-offsets.c [new file with mode: 0644]
arch/m32r/kernel/smp.c
arch/m68k/Makefile
arch/m68k/amiga/amisound.c
arch/m68k/fpsp040/skeleton.S
arch/m68k/ifpsp060/iskeleton.S
arch/m68k/kernel/entry.S
arch/m68k/kernel/head.S
arch/m68k/mac/macboing.c
arch/m68k/math-emu/fp_emu.h
arch/m68knommu/Makefile
arch/m68knommu/platform/68360/head-ram.S [new file with mode: 0644]
arch/m68knommu/platform/68360/head-rom.S [new file with mode: 0644]
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/configs/tb0287_defconfig [new file with mode: 0644]
arch/mips/kernel/asm-offsets.c [new file with mode: 0644]
arch/mips/kernel/genrtc.c
arch/mips/kernel/i8259.c
arch/mips/kernel/irixioctl.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/offset.c [deleted file]
arch/mips/kernel/r2300_fpu.S
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/r6000_fpu.S
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/syscall.c
arch/mips/kernel/sysirix.c
arch/mips/lib-32/memset.S
arch/mips/lib-64/memset.S
arch/mips/lib/dec_and_lock.c
arch/mips/lib/memcpy.S
arch/mips/lib/strlen_user.S
arch/mips/lib/strncpy_user.S
arch/mips/lib/strnlen_user.S
arch/mips/pci/Makefile
arch/mips/pci/fixup-tb0287.c [new file with mode: 0644]
arch/parisc/Makefile
arch/parisc/hpux/gate.S
arch/parisc/hpux/wrappers.S
arch/parisc/kernel/entry.S
arch/parisc/kernel/head.S
arch/parisc/kernel/process.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/syscall.S
arch/parisc/lib/Makefile
arch/parisc/lib/bitops.c
arch/parisc/lib/debuglocks.c [deleted file]
arch/parisc/lib/fixup.S
arch/ppc/8xx_io/cs4218_tdm.c
arch/ppc/Kconfig
arch/ppc/Makefile
arch/ppc/boot/common/ns16550.c
arch/ppc/boot/common/util.S
arch/ppc/kernel/Makefile
arch/ppc/kernel/cpu_setup_6xx.S
arch/ppc/kernel/cpu_setup_power4.S
arch/ppc/kernel/dma-mapping.c
arch/ppc/kernel/entry.S
arch/ppc/kernel/fpu.S
arch/ppc/kernel/head.S
arch/ppc/kernel/head_44x.S
arch/ppc/kernel/head_4xx.S
arch/ppc/kernel/head_8xx.S
arch/ppc/kernel/head_fsl_booke.S
arch/ppc/kernel/idle.c
arch/ppc/kernel/idle_6xx.S
arch/ppc/kernel/idle_power4.S
arch/ppc/kernel/misc.S
arch/ppc/kernel/smp.c
arch/ppc/kernel/swsusp.S
arch/ppc/kernel/traps.c
arch/ppc/lib/Makefile
arch/ppc/lib/dec_and_lock.c
arch/ppc/mm/fault.c
arch/ppc/mm/hashtable.S
arch/ppc/platforms/4xx/ebony.c
arch/ppc/platforms/hdpu.c
arch/ppc/platforms/pmac_sleep.S
arch/ppc/platforms/pmac_smp.c
arch/ppc/syslib/cpc700_pic.c
arch/ppc/syslib/i8259.c
arch/ppc/syslib/ibm440gx_common.c
arch/ppc/syslib/mv64x60.c
arch/ppc/syslib/open_pic2.c
arch/ppc/syslib/ppc403_pic.c
arch/ppc/syslib/qspan_pci.c
arch/ppc/syslib/xilinx_pic.c
arch/ppc64/Makefile
arch/ppc64/kernel/cpu_setup_power4.S
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/head.S
arch/ppc64/kernel/iSeries_pci.c
arch/ppc64/kernel/idle_power4.S
arch/ppc64/kernel/maple_pci.c
arch/ppc64/kernel/misc.S
arch/ppc64/kernel/pSeries_setup.c
arch/ppc64/kernel/pSeries_smp.c
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/pmac_pci.c
arch/ppc64/kernel/pmac_setup.c
arch/ppc64/kernel/pmc.c
arch/ppc64/kernel/process.c
arch/ppc64/kernel/ptrace.c
arch/ppc64/kernel/ptrace32.c
arch/ppc64/kernel/ras.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/signal.c
arch/ppc64/kernel/signal32.c
arch/ppc64/kernel/vdso32/cacheflush.S
arch/ppc64/kernel/vdso32/datapage.S
arch/ppc64/kernel/vdso32/gettimeofday.S
arch/ppc64/kernel/vdso64/cacheflush.S
arch/ppc64/kernel/vdso64/datapage.S
arch/ppc64/kernel/vdso64/gettimeofday.S
arch/ppc64/kernel/xics.c
arch/ppc64/lib/dec_and_lock.c
arch/ppc64/lib/locks.c
arch/ppc64/mm/fault.c
arch/ppc64/mm/hash_low.S
arch/ppc64/mm/slb_low.S
arch/ppc64/xmon/privinst.h
arch/ppc64/xmon/xmon.c
arch/s390/Makefile
arch/s390/kernel/compat_linux.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/head64.S
arch/s390/lib/spinlock.c
arch/s390/lib/uaccess.S
arch/s390/lib/uaccess64.S
arch/sh/Makefile
arch/sh/boards/adx/irq_maskreg.c
arch/sh/boards/bigsur/io.c
arch/sh/boards/bigsur/irq.c
arch/sh/boards/cqreek/irq.c
arch/sh/boards/harp/irq.c
arch/sh/boards/overdrive/irq.c
arch/sh/boards/renesas/hs7751rvoip/irq.c
arch/sh/boards/renesas/rts7751r2d/irq.c
arch/sh/boards/renesas/systemh/irq.c
arch/sh/boards/superh/microdev/irq.c
arch/sh/cchips/hd6446x/hd64465/io.c
arch/sh/cchips/voyagergx/irq.c
arch/sh/kernel/cpu/irq_imask.c
arch/sh/kernel/cpu/irq_ipr.c
arch/sh/kernel/cpu/sh4/irq_intc2.c
arch/sh64/Makefile
arch/sh64/kernel/irq_intc.c
arch/sparc/Makefile
arch/sparc/kernel/entry.S
arch/sparc/kernel/sclow.S
arch/sparc/kernel/sparc_ksyms.c
arch/sparc/lib/Makefile
arch/sparc/lib/atomic32.c
arch/sparc/lib/debuglocks.c [deleted file]
arch/sparc/mm/hypersparc.S
arch/sparc/mm/swift.S
arch/sparc/mm/tsunami.S
arch/sparc/mm/viking.S
arch/sparc64/kernel/asm-offsets.c [new file with mode: 0644]
arch/sparc64/kernel/process.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/lib/Makefile
arch/sparc64/lib/debuglocks.c [deleted file]
arch/sparc64/solaris/ioctl.c
arch/sparc64/solaris/timod.c
arch/um/Makefile
arch/um/include/mem.h
arch/um/kernel/asm-offsets.c [new file with mode: 0644]
arch/um/kernel/dyn.lds.S
arch/um/kernel/ksyms.c
arch/um/kernel/physmem.c
arch/um/kernel/trap_kern.c
arch/um/kernel/uml.lds.S
arch/v850/Makefile
arch/v850/kernel/asm-consts.c [deleted file]
arch/v850/kernel/asm-offsets.c [new file with mode: 0644]
arch/v850/kernel/entry.S
arch/v850/kernel/irq.c
arch/v850/kernel/setup.c
arch/v850/kernel/sim.c
arch/x86_64/Makefile
arch/x86_64/boot/Makefile
arch/x86_64/boot/compressed/misc.c
arch/x86_64/defconfig
arch/x86_64/ia32/ia32_ioctl.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/ia32/sys_ia32.c
arch/x86_64/ia32/vsyscall-syscall.S
arch/x86_64/ia32/vsyscall-sysenter.S
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/acpi/sleep.c
arch/x86_64/kernel/aperture.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/asm-offsets.c
arch/x86_64/kernel/crash.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/genapic.c
arch/x86_64/kernel/genapic_cluster.c
arch/x86_64/kernel/genapic_flat.c
arch/x86_64/kernel/head.S
arch/x86_64/kernel/i8259.c
arch/x86_64/kernel/init_task.c
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/irq.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mpparse.c
arch/x86_64/kernel/msr.c [deleted file]
arch/x86_64/kernel/nmi.c
arch/x86_64/kernel/pci-gart.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/suspend.c
arch/x86_64/kernel/suspend_asm.S
arch/x86_64/kernel/time.c
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/kernel/vsyscall.c
arch/x86_64/lib/copy_user.S
arch/x86_64/lib/getuser.S
arch/x86_64/lib/putuser.S
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/k8topology.c
arch/x86_64/mm/numa.c
arch/x86_64/mm/srat.c
arch/x86_64/pci/k8-bus.c
arch/x86_64/pci/mmconfig.c
arch/xtensa/Makefile
arch/xtensa/kernel/align.S
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/process.c
arch/xtensa/kernel/vectors.S
drivers/acorn/block/fd1772.c
drivers/acpi/sleep/main.c
drivers/acpi/sleep/poweroff.c
drivers/acpi/sleep/proc.c
drivers/atm/idt77105.c
drivers/atm/iphase.c
drivers/base/dmapool.c
drivers/block/acsi.c
drivers/block/acsi_slm.c
drivers/block/ataflop.c
drivers/block/cciss.c
drivers/block/cfq-iosched.c
drivers/block/deadline-iosched.c
drivers/block/floppy.c
drivers/block/paride/pcd.c
drivers/block/paride/pf.c
drivers/block/paride/pg.c
drivers/block/paride/pt.c
drivers/block/ps2esdi.c
drivers/block/swim3.c
drivers/block/swim_iop.c
drivers/block/umem.c
drivers/block/xd.c
drivers/block/z2ram.c
drivers/cdrom/aztcd.c
drivers/cdrom/gscd.c
drivers/cdrom/optcd.c
drivers/cdrom/sbpcd.c
drivers/cdrom/sjcd.c
drivers/cdrom/sonycd535.c
drivers/char/agp/backend.c
drivers/char/applicom.c
drivers/char/cyclades.c
drivers/char/ftape/lowlevel/fdc-io.c
drivers/char/hangcheck-timer.c
drivers/char/hpet.c
drivers/char/hw_random.c
drivers/char/ip2/i2lib.c
drivers/char/ip2main.c
drivers/char/ipmi/ipmi_devintf.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/istallion.c
drivers/char/keyboard.c
drivers/char/lcd.c
drivers/char/lp.c
drivers/char/mxser.c
drivers/char/n_tty.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/pty.c
drivers/char/synclink.c
drivers/char/synclinkmp.c
drivers/char/tty_io.c
drivers/char/vt.c
drivers/char/watchdog/mixcomwd.c
drivers/ide/ide-io.c
drivers/ide/ide-tape.c
drivers/ide/ide-timing.h
drivers/ide/legacy/ide-cs.c
drivers/ide/pci/hpt366.c
drivers/ieee1394/video1394.c
drivers/infiniband/Kconfig
drivers/infiniband/core/Makefile
drivers/infiniband/core/cm.c
drivers/infiniband/core/mad_rmpp.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/ucm.c
drivers/infiniband/core/ucm.h
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/uverbs_main.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/input/evdev.c
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/sunkbd.c
drivers/input/mouse/Makefile
drivers/input/mouse/alps.c
drivers/input/mouse/logips2pp.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse.h
drivers/input/mouse/trackpoint.c [new file with mode: 0644]
drivers/input/mouse/trackpoint.h [new file with mode: 0644]
drivers/input/serio/i8042-io.h
drivers/input/serio/i8042-ip22io.h
drivers/input/serio/i8042-jazzio.h
drivers/input/serio/i8042-sparcio.h
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/isdn/i4l/isdn_bsdcomp.c
drivers/isdn/i4l/isdn_common.c
drivers/md/bitmap.c
drivers/md/dm-exception-store.c
drivers/md/dm-raid1.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid6main.c
drivers/media/Makefile
drivers/media/common/ir-common.c
drivers/media/common/saa7146_core.c
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_i2c.c
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/bt8xx/bt878.h
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/bt8xx/dvb-bt8xx.h
drivers/media/dvb/cinergyT2/Kconfig
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/demux.h
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/dvb/dvb-core/dvb_demux.h
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/cxusb.h
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u-fe.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-init.c
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/dvb-usb/vp702x-fe.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/vp702x.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/vp702x.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/vp7045.c
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/s5h1420.h
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0297.h
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/btcx-risc.c
drivers/media/video/btcx-risc.h
drivers/media/video/bttv-cards.c
drivers/media/video/bttv-driver.c
drivers/media/video/bttv-gpio.c
drivers/media/video/bttv-i2c.c
drivers/media/video/bttv-if.c
drivers/media/video/bttv-risc.c
drivers/media/video/bttv-vbi.c
drivers/media/video/bttv.h
drivers/media/video/bttvp.h
drivers/media/video/cpia_usb.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-reg.h
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-vbi.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/ir-kbd-gpio.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/msp3400.c
drivers/media/video/msp3400.h
drivers/media/video/mt20xx.c
drivers/media/video/rds.h [new file with mode: 0644]
drivers/media/video/saa6588.c [new file with mode: 0644]
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-oss.c
drivers/media/video/saa7134/saa7134-reg.h
drivers/media/video/saa7134/saa7134-ts.c
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134-vbi.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/stradis.c
drivers/media/video/tda8290.c
drivers/media/video/tda9887.c
drivers/media/video/tea5767.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-simple.c
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/tvmixer.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/video-buf-dvb.c
drivers/media/video/video-buf.c
drivers/media/video/zoran_driver.c
drivers/media/video/zr36120.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/ucb1x00-assabet.c [new file with mode: 0644]
drivers/mfd/ucb1x00-core.c [new file with mode: 0644]
drivers/mfd/ucb1x00-ts.c [new file with mode: 0644]
drivers/mfd/ucb1x00.h [new file with mode: 0644]
drivers/misc/hdpuftrs/hdpu_cpustate.c
drivers/mmc/wbsd.c
drivers/mtd/devices/mtdram.c
drivers/mtd/ftl.c
drivers/mtd/maps/uclinux.c
drivers/net/Kconfig
drivers/net/atari_bionet.c
drivers/net/atari_pamsnet.c
drivers/net/bsd_comp.c
drivers/net/cris/eth_v10.c
drivers/net/cs89x0.c
drivers/net/fec.c
drivers/net/fec.h
drivers/net/hamradio/yam.c
drivers/net/mv643xx_eth.c
drivers/net/ppp_generic.c
drivers/net/sungem.c
drivers/net/sunhme.c
drivers/net/tulip/de4x5.c
drivers/parisc/iosapic.c
drivers/parisc/lasi.c
drivers/parport/ieee1284.c
drivers/parport/ieee1284_ops.c
drivers/parport/parport_pc.c
drivers/pci/hotplug.c
drivers/pci/hotplug/pciehprm_acpi.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-bus.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/omap_cf.c [new file with mode: 0644]
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/yenta_socket.c
drivers/sbus/char/aurora.c
drivers/sbus/char/bbc_envctrl.c
drivers/sbus/char/envctrl.c
drivers/scsi/53c7xx.c
drivers/scsi/ch.c
drivers/scsi/cpqfcTSinit.c
drivers/scsi/ibmmca.c
drivers/scsi/osst.c
drivers/scsi/pluto.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/serial/8250.c
drivers/serial/mcfserial.c
drivers/serial/serial_txx9.c
drivers/telephony/ixj.c
drivers/usb/host/hc_crisv10.c
drivers/usb/input/hid-core.c
drivers/usb/input/hid-debug.h
drivers/usb/input/hid-input.c
drivers/usb/input/hid.h
drivers/usb/input/hiddev.c
drivers/usb/media/stv680.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/aty/aty128fb.c
drivers/video/aty/atyfb_base.c
drivers/video/aty/radeon_base.c
drivers/video/console/bitblit.c
drivers/video/console/fbcon.c
drivers/video/console/fbcon.h
drivers/video/console/vgacon.c
drivers/video/cyblafb.c [new file with mode: 0644]
drivers/video/fbcvt.c [new file with mode: 0644]
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/geode/Kconfig
drivers/video/geode/display_gx1.c
drivers/video/geode/geodefb.h
drivers/video/geode/gx1fb_core.c
drivers/video/geode/video_cs5530.c
drivers/video/i810/Makefile
drivers/video/i810/i810-i2c.c [new file with mode: 0644]
drivers/video/i810/i810.h
drivers/video/i810/i810_main.c
drivers/video/i810/i810_main.h
drivers/video/intelfb/intelfb.h
drivers/video/intelfb/intelfbdrv.c
drivers/video/intelfb/intelfbhw.c
drivers/video/matrox/matroxfb_misc.c
drivers/video/modedb.c
drivers/video/nvidia/nv_i2c.c
drivers/video/nvidia/nv_local.h
drivers/video/nvidia/nv_of.c
drivers/video/nvidia/nv_proto.h
drivers/video/nvidia/nv_setup.c
drivers/video/nvidia/nvidia.c
drivers/video/pxafb.c
drivers/video/pxafb.h
drivers/video/s3c2410fb.c [new file with mode: 0644]
drivers/video/s3c2410fb.h [new file with mode: 0644]
drivers/video/savage/savagefb-i2c.c
drivers/video/savage/savagefb.h
drivers/video/savage/savagefb_driver.c
drivers/video/sis/300vtbl.h
drivers/video/sis/310vtbl.h
drivers/video/sis/Makefile
drivers/video/sis/init.c
drivers/video/sis/init.h
drivers/video/sis/init301.c
drivers/video/sis/init301.h
drivers/video/sis/initdef.h
drivers/video/sis/initextlfb.c [new file with mode: 0644]
drivers/video/sis/oem300.h
drivers/video/sis/oem310.h
drivers/video/sis/osdef.h
drivers/video/sis/sis.h
drivers/video/sis/sis_accel.c
drivers/video/sis/sis_accel.h
drivers/video/sis/sis_main.c
drivers/video/sis/sis_main.h
drivers/video/sis/vgatypes.h
drivers/video/sis/vstruct.h
drivers/video/tridentfb.c
drivers/video/vesafb.c
drivers/video/vgastate.c
drivers/w1/w1_ds2433.c
fs/9p/9p.c [new file with mode: 0644]
fs/9p/9p.h [new file with mode: 0644]
fs/9p/Makefile [new file with mode: 0644]
fs/9p/conv.c [new file with mode: 0644]
fs/9p/conv.h [new file with mode: 0644]
fs/9p/debug.h [new file with mode: 0644]
fs/9p/error.c [new file with mode: 0644]
fs/9p/error.h [new file with mode: 0644]
fs/9p/fid.c [new file with mode: 0644]
fs/9p/fid.h [new file with mode: 0644]
fs/9p/mux.c [new file with mode: 0644]
fs/9p/mux.h [new file with mode: 0644]
fs/9p/trans_fd.c [new file with mode: 0644]
fs/9p/trans_sock.c [new file with mode: 0644]
fs/9p/transport.h [new file with mode: 0644]
fs/9p/v9fs.c [new file with mode: 0644]
fs/9p/v9fs.h [new file with mode: 0644]
fs/9p/v9fs_vfs.h [new file with mode: 0644]
fs/9p/vfs_dentry.c [new file with mode: 0644]
fs/9p/vfs_dir.c [new file with mode: 0644]
fs/9p/vfs_file.c [new file with mode: 0644]
fs/9p/vfs_inode.c [new file with mode: 0644]
fs/9p/vfs_super.c [new file with mode: 0644]
fs/Kconfig
fs/Makefile
fs/affs/inode.c
fs/aio.c
fs/autofs/autofs_i.h
fs/autofs/dirhash.c
fs/autofs/inode.c
fs/bfs/bfs.h
fs/bfs/dir.c
fs/bfs/file.c
fs/bfs/inode.c
fs/buffer.c
fs/cifs/connect.c
fs/compat.c
fs/compat_ioctl.c
fs/cramfs/uncompress.c
fs/dcache.c
fs/exec.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/xattr.h
fs/ext2/xattr_security.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext3/xattr.h
fs/ext3/xattr_security.c
fs/fat/inode.c
fs/fcntl.c
fs/file.c
fs/file_table.c
fs/fuse/Makefile [new file with mode: 0644]
fs/fuse/dev.c [new file with mode: 0644]
fs/fuse/dir.c [new file with mode: 0644]
fs/fuse/file.c [new file with mode: 0644]
fs/fuse/fuse_i.h [new file with mode: 0644]
fs/fuse/inode.c [new file with mode: 0644]
fs/hostfs/hostfs_kern.c
fs/hpfs/inode.c
fs/inode.c
fs/jbd/transaction.c
fs/jffs/inode-v23.c
fs/jffs/intrep.c
fs/jfs/acl.c
fs/jfs/inode.c
fs/jfs/jfs_acl.h
fs/jfs/jfs_xattr.h
fs/jfs/namei.c
fs/jfs/xattr.c
fs/lockd/clntproc.c
fs/locks.c
fs/minix/inode.c
fs/namei.c
fs/namespace.c
fs/ncpfs/inode.c
fs/nfs/inode.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/ntfs/aops.c
fs/open.c
fs/pipe.c
fs/proc/array.c
fs/proc/base.c
fs/proc/inode.c
fs/qnx4/inode.c
fs/reiserfs/inode.c
fs/reiserfs/journal.c
fs/reiserfs/super.c
fs/select.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/sysv/inode.c
fs/udf/inode.c
fs/ufs/inode.c
fs/xfs/linux-2.6/time.h
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/support/ktrace.c
include/asm-alpha/spinlock.h
include/asm-alpha/spinlock_types.h [new file with mode: 0644]
include/asm-arm/arch-pxa/pxafb.h
include/asm-arm/arch-s3c2410/fb.h [new file with mode: 0644]
include/asm-arm/arch-s3c2410/regs-lcd.h
include/asm-arm/spinlock.h
include/asm-arm/spinlock_types.h [new file with mode: 0644]
include/asm-arm/unistd.h
include/asm-arm26/hardirq.h
include/asm-generic/tlb.h
include/asm-generic/vmlinux.lds.h
include/asm-i386/apic.h
include/asm-i386/div64.h
include/asm-i386/mach-default/mach_reboot.h
include/asm-i386/mmzone.h
include/asm-i386/numa.h [new file with mode: 0644]
include/asm-i386/processor.h
include/asm-i386/spinlock.h
include/asm-i386/spinlock_types.h [new file with mode: 0644]
include/asm-i386/thread_info.h
include/asm-i386/topology.h
include/asm-i386/unistd.h
include/asm-ia64/mca.h
include/asm-ia64/mca_asm.h
include/asm-ia64/ptrace.h
include/asm-ia64/sn/sn_feature_sets.h [new file with mode: 0644]
include/asm-ia64/sn/sn_sal.h
include/asm-ia64/spinlock.h
include/asm-ia64/spinlock_types.h [new file with mode: 0644]
include/asm-ia64/system.h
include/asm-ia64/thread_info.h
include/asm-ia64/unwind.h
include/asm-m32r/spinlock.h
include/asm-m32r/spinlock_types.h [new file with mode: 0644]
include/asm-m68knommu/bitops.h
include/asm-m68knommu/checksum.h
include/asm-m68knommu/m527xsim.h
include/asm-m68knommu/m528xsim.h
include/asm-m68knommu/mcfcache.h
include/asm-m68knommu/mcfdma.h
include/asm-mips/asmmacro-32.h
include/asm-mips/asmmacro-64.h
include/asm-mips/irq.h
include/asm-mips/sim.h
include/asm-mips/spinlock.h
include/asm-mips/spinlock_types.h [new file with mode: 0644]
include/asm-mips/stackframe.h
include/asm-mips/vr41xx/tb0287.h [new file with mode: 0644]
include/asm-parisc/assembly.h
include/asm-parisc/atomic.h
include/asm-parisc/bitops.h
include/asm-parisc/cacheflush.h
include/asm-parisc/processor.h
include/asm-parisc/spinlock.h
include/asm-parisc/spinlock_types.h [new file with mode: 0644]
include/asm-parisc/system.h
include/asm-powerpc/siginfo.h
include/asm-ppc/irq.h
include/asm-ppc/ptrace.h
include/asm-ppc/reg.h
include/asm-ppc/smp.h
include/asm-ppc/spinlock.h
include/asm-ppc/spinlock_types.h [new file with mode: 0644]
include/asm-ppc/system.h
include/asm-ppc64/hvcall.h
include/asm-ppc64/machdep.h
include/asm-ppc64/pci-bridge.h
include/asm-ppc64/plpar_wrappers.h
include/asm-ppc64/processor.h
include/asm-ppc64/ptrace-common.h
include/asm-ppc64/ptrace.h
include/asm-ppc64/spinlock.h
include/asm-ppc64/spinlock_types.h [new file with mode: 0644]
include/asm-ppc64/system.h
include/asm-s390/spinlock.h
include/asm-s390/spinlock_types.h [new file with mode: 0644]
include/asm-sh/irq.h
include/asm-sh/spinlock.h
include/asm-sh/spinlock_types.h [new file with mode: 0644]
include/asm-sparc/ptrace.h
include/asm-sparc/spinlock.h
include/asm-sparc/spinlock_types.h [new file with mode: 0644]
include/asm-sparc64/spinlock.h
include/asm-sparc64/spinlock_types.h [new file with mode: 0644]
include/asm-um/page.h
include/asm-um/pgtable.h
include/asm-um/spinlock_types.h [new file with mode: 0644]
include/asm-x86_64/apic.h
include/asm-x86_64/apicdef.h
include/asm-x86_64/bug.h
include/asm-x86_64/calling.h
include/asm-x86_64/current.h
include/asm-x86_64/desc.h
include/asm-x86_64/dma-mapping.h
include/asm-x86_64/dwarf2.h
include/asm-x86_64/fixmap.h
include/asm-x86_64/hardirq.h
include/asm-x86_64/hw_irq.h
include/asm-x86_64/io.h
include/asm-x86_64/ipi.h
include/asm-x86_64/irq.h
include/asm-x86_64/kdebug.h
include/asm-x86_64/local.h
include/asm-x86_64/mmzone.h
include/asm-x86_64/msr.h
include/asm-x86_64/numa.h
include/asm-x86_64/page.h
include/asm-x86_64/pci.h
include/asm-x86_64/pda.h
include/asm-x86_64/pgalloc.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/processor.h
include/asm-x86_64/proto.h
include/asm-x86_64/signal.h
include/asm-x86_64/smp.h
include/asm-x86_64/spinlock.h
include/asm-x86_64/spinlock_types.h [new file with mode: 0644]
include/asm-x86_64/system.h
include/asm-x86_64/timex.h
include/asm-x86_64/tlbflush.h
include/asm-x86_64/topology.h
include/asm-x86_64/vsyscall.h
include/asm-xtensa/ptrace.h
include/asm-xtensa/uaccess.h
include/linux/bfs_fs.h
include/linux/bio.h
include/linux/bit_spinlock.h [new file with mode: 0644]
include/linux/blkdev.h
include/linux/chio.h
include/linux/crc16.h
include/linux/dccp.h
include/linux/dmapool.h
include/linux/dmi.h
include/linux/fb.h
include/linux/file.h
include/linux/fs.h
include/linux/fuse.h [new file with mode: 0644]
include/linux/in6.h
include/linux/init_task.h
include/linux/input.h
include/linux/interrupt.h
include/linux/ipv6.h
include/linux/jbd.h
include/linux/jiffies.h
include/linux/pci.h
include/linux/radix-tree.h
include/linux/raid/bitmap.h
include/linux/raid/linear.h
include/linux/raid/md_k.h
include/linux/raid/md_p.h
include/linux/raid/raid1.h
include/linux/raid/raid5.h
include/linux/rcupdate.h
include/linux/rcuref.h [new file with mode: 0644]
include/linux/reiserfs_fs.h
include/linux/sched.h
include/linux/security.h
include/linux/slab.h
include/linux/spinlock.h
include/linux/spinlock_api_smp.h [new file with mode: 0644]
include/linux/spinlock_api_up.h [new file with mode: 0644]
include/linux/spinlock_types.h [new file with mode: 0644]
include/linux/spinlock_types_up.h [new file with mode: 0644]
include/linux/spinlock_up.h [new file with mode: 0644]
include/linux/time.h
include/linux/timer.h
include/linux/tty.h
include/linux/videodev.h
include/linux/videodev2.h
include/linux/writeback.h
include/media/audiochip.h
include/media/id.h
include/media/ir-common.h
include/media/saa7146.h
include/media/tuner.h
include/media/tveeprom.h
include/media/video-buf.h
include/pcmcia/ds.h
include/rdma/ib_cm.h
include/rdma/ib_mad.h
include/rdma/ib_sa.h
include/rdma/ib_user_cm.h
include/rdma/ib_user_verbs.h
include/sound/pcm.h
include/sound/tea575x-tuner.h
include/video/cyblafb.h [new file with mode: 0644]
include/video/sisfb.h
ipc/mqueue.c
kernel/Makefile
kernel/acct.c
kernel/compat.c
kernel/cpuset.c
kernel/exit.c
kernel/fork.c
kernel/rcupdate.c
kernel/sched.c
kernel/signal.c
kernel/softirq.c
kernel/spinlock.c
kernel/timer.c
lib/Kconfig.debug
lib/Makefile
lib/dec_and_lock.c
lib/kernel_lock.c
lib/radix-tree.c
lib/sort.c
lib/spinlock_debug.c [new file with mode: 0644]
mm/bootmem.c
mm/filemap.c
mm/memory.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/swap_state.c
mm/swapfile.c
mm/vmalloc.c
net/atm/mpc.c
net/core/dst.c
net/core/netpoll.c
net/core/pktgen.c
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.h
net/dccp/ccids/lib/packet_history.h
net/dccp/dccp.h
net/dccp/input.c
net/dccp/ipv4.c
net/dccp/minisocks.c
net/dccp/options.c
net/dccp/output.c
net/decnet/dn_route.c
net/ipv4/af_inet.c
net/ipv4/fib_trie.c
net/ipv4/inetpeer.c
net/ipv4/netfilter/ipt_owner.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/exthdrs.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_flowlabel.c
net/ipv6/netfilter/ip6t_owner.c
net/ipv6/netfilter/ip6t_rt.c
net/netrom/nr_loopback.c
net/sched/sch_api.c
scripts/Kbuild.include
scripts/reference_discarded.pl
security/dummy.c
security/selinux/hooks.c
sound/isa/sb/sb16_csp.c
sound/oss/midibuf.c
sound/oss/skeleton.c [deleted file]
sound/oss/soundcard.c
sound/oss/sys_timer.c
sound/oss/uart6850.c

diff --git a/COPYING b/COPYING
index 2a7e338ec2fc6aac461a11fe8049799e65639166..ca442d313d86dc67e0a2e5d584b465bd382cbf5c 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -18,7 +18,7 @@
                       Version 2, June 1991
 
  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -321,7 +321,7 @@ the "copyright" line and a pointer to where the full notice is found.
 
     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
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 
 Also add information on how to contact you by electronic and paper mail.
index f28a24e0279b4c01aa8596e3f296ec50ef0ad70a..433cf5e9ae04bd17a04d50c320db9f100c68da63 100644 (file)
@@ -46,6 +46,8 @@ SubmittingPatches
        - procedure to get a source patch included into the kernel tree.
 VGA-softcursor.txt
        - how to change your VGA cursor from a blinking underscore.
+applying-patches.txt
+       - description of various trees and how to apply their patches.
 arm/
        - directory with info about Linux on the ARM architecture.
 basic_profiling.txt
@@ -275,7 +277,7 @@ tty.txt
 unicode.txt
        - info on the Unicode character/font mapping used in Linux.
 uml/
-       - directory with infomation about User Mode Linux.
+       - directory with information about User Mode Linux.
 usb/
        - directory with info regarding the Universal Serial Bus.
 video4linux/
index f25b3953f51398a023afd8b633aa5168313ccc4a..22e5f9036f3c193f88d14611b2e5fe669b2c9b9e 100644 (file)
@@ -236,6 +236,9 @@ ugly), but try to avoid excess.  Instead, put the comments at the head
 of the function, telling people what it does, and possibly WHY it does
 it.
 
+When commenting the kernel API functions, please use the kerneldoc format.
+See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc
+for details.
 
                Chapter 8: You've made a mess of it
 
index 6ee3cd6134dfad024bccff633ac2bece79fc0db6..1af0f2d5022066f1a205ad5265771e3ab112c018 100644 (file)
@@ -121,7 +121,7 @@ pool's device.
                        dma_addr_t addr);
 
 This puts memory back into the pool.  The pool is what was passed to
-the the pool allocation routine; the cpu and dma addresses are what
+the pool allocation routine; the cpu and dma addresses are what
 were returned when that routine allocated the memory being freed.
 
 
diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt
new file mode 100644 (file)
index 0000000..705f6be
--- /dev/null
@@ -0,0 +1,151 @@
+                        DMA with ISA and LPC devices
+                        ============================
+
+                      Pierre Ossman <drzeus@drzeus.cx>
+
+This document describes how to do DMA transfers using the old ISA DMA
+controller. Even though ISA is more or less dead today the LPC bus
+uses the same DMA system so it will be around for quite some time.
+
+Part I - Headers and dependencies
+---------------------------------
+
+To do ISA style DMA you need to include two headers:
+
+#include <linux/dma-mapping.h>
+#include <asm/dma.h>
+
+The first is the generic DMA API used to convert virtual addresses to
+physical addresses (see Documentation/DMA-API.txt for details).
+
+The second contains the routines specific to ISA DMA transfers. Since
+this is not present on all platforms make sure you construct your
+Kconfig to be dependent on ISA_DMA_API (not ISA) so that nobody tries
+to build your driver on unsupported platforms.
+
+Part II - Buffer allocation
+---------------------------
+
+The ISA DMA controller has some very strict requirements on which
+memory it can access so extra care must be taken when allocating
+buffers.
+
+(You usually need a special buffer for DMA transfers instead of
+transferring directly to and from your normal data structures.)
+
+The DMA-able address space is the lowest 16 MB of _physical_ memory.
+Also the transfer block may not cross page boundaries (which are 64
+or 128 KiB depending on which channel you use).
+
+In order to allocate a piece of memory that satisfies all these
+requirements you pass the flag GFP_DMA to kmalloc.
+
+Unfortunately the memory available for ISA DMA is scarce so unless you
+allocate the memory during boot-up it's a good idea to also pass
+__GFP_REPEAT and __GFP_NOWARN to make the allocater try a bit harder.
+
+(This scarcity also means that you should allocate the buffer as
+early as possible and not release it until the driver is unloaded.)
+
+Part III - Address translation
+------------------------------
+
+To translate the virtual address to a physical use the normal DMA
+API. Do _not_ use isa_virt_to_phys() even though it does the same
+thing. The reason for this is that the function isa_virt_to_phys()
+will require a Kconfig dependency to ISA, not just ISA_DMA_API which
+is really all you need. Remember that even though the DMA controller
+has its origins in ISA it is used elsewhere.
+
+Note: x86_64 had a broken DMA API when it came to ISA but has since
+been fixed. If your arch has problems then fix the DMA API instead of
+reverting to the ISA functions.
+
+Part IV - Channels
+------------------
+
+A normal ISA DMA controller has 8 channels. The lower four are for
+8-bit transfers and the upper four are for 16-bit transfers.
+
+(Actually the DMA controller is really two separate controllers where
+channel 4 is used to give DMA access for the second controller (0-3).
+This means that of the four 16-bits channels only three are usable.)
+
+You allocate these in a similar fashion as all basic resources:
+
+extern int request_dma(unsigned int dmanr, const char * device_id);
+extern void free_dma(unsigned int dmanr);
+
+The ability to use 16-bit or 8-bit transfers is _not_ up to you as a
+driver author but depends on what the hardware supports. Check your
+specs or test different channels.
+
+Part V - Transfer data
+----------------------
+
+Now for the good stuff, the actual DMA transfer. :)
+
+Before you use any ISA DMA routines you need to claim the DMA lock
+using claim_dma_lock(). The reason is that some DMA operations are
+not atomic so only one driver may fiddle with the registers at a
+time.
+
+The first time you use the DMA controller you should call
+clear_dma_ff(). This clears an internal register in the DMA
+controller that is used for the non-atomic operations. As long as you
+(and everyone else) uses the locking functions then you only need to
+reset this once.
+
+Next, you tell the controller in which direction you intend to do the
+transfer using set_dma_mode(). Currently you have the options
+DMA_MODE_READ and DMA_MODE_WRITE.
+
+Set the address from where the transfer should start (this needs to
+be 16-bit aligned for 16-bit transfers) and how many bytes to
+transfer. Note that it's _bytes_. The DMA routines will do all the
+required translation to values that the DMA controller understands.
+
+The final step is enabling the DMA channel and releasing the DMA
+lock.
+
+Once the DMA transfer is finished (or timed out) you should disable
+the channel again. You should also check get_dma_residue() to make
+sure that all data has been transfered.
+
+Example:
+
+int flags, residue;
+
+flags = claim_dma_lock();
+
+clear_dma_ff();
+
+set_dma_mode(channel, DMA_MODE_WRITE);
+set_dma_addr(channel, phys_addr);
+set_dma_count(channel, num_bytes);
+
+dma_enable(channel);
+
+release_dma_lock(flags);
+
+while (!device_done());
+
+flags = claim_dma_lock();
+
+dma_disable(channel);
+
+residue = dma_get_residue(channel);
+if (residue != 0)
+       printk(KERN_ERR "driver: Incomplete DMA transfer!"
+               " %d bytes left!\n", residue);
+
+release_dma_lock(flags);
+
+Part VI - Suspend/resume
+------------------------
+
+It is the driver's responsibility to make sure that the machine isn't
+suspended while a DMA transfer is in progress. Also, all DMA settings
+are lost when the system suspends so if your driver relies on the DMA
+controller being in a certain state then you have to restore these
+registers upon resume.
index 1ef6f43c6d8f6a2d3f1be39ac6fcf4781ddb746d..341aaa4ce481a5a9af1f85d17be35e83e2b8b075 100644 (file)
@@ -116,7 +116,7 @@ filesystem. Almost.
 
 You still need to actually journal your filesystem changes, this
 is done by wrapping them into transactions. Additionally you
-also need to wrap the modification of each of the the buffers
+also need to wrap the modification of each of the buffers
 with calls to the journal layer, so it knows what the modifications
 you are actually making are. To do this use  journal_start() which
 returns a transaction handle.
@@ -128,7 +128,7 @@ and its counterpart journal_stop(), which indicates the end of a transaction
 are nestable calls, so you can reenter a transaction if necessary,
 but remember you must call journal_stop() the same number of times as
 journal_start() before the transaction is completed (or more accurately
-leaves the the update phase). Ext3/VFS makes use of this feature to simplify 
+leaves the update phase). Ext3/VFS makes use of this feature to simplify
 quota support.
 </para>
 
index 49a9ef82d575fe99c60fe1ad4b382cf221a2ce86..6367bba32d22256dae461b2649c3f51367af93bc 100644 (file)
@@ -8,8 +8,7 @@
   
   <authorgroup>
    <author>
-    <firstname>Paul</firstname>
-    <othername>Rusty</othername>
+    <firstname>Rusty</firstname>
     <surname>Russell</surname>
     <affiliation>
      <address>
@@ -20,7 +19,7 @@
   </authorgroup>
 
   <copyright>
-   <year>2001</year>
+   <year>2005</year>
    <holder>Rusty Russell</holder>
   </copyright>
 
@@ -64,7 +63,7 @@
  <chapter id="introduction">
   <title>Introduction</title>
   <para>
-   Welcome, gentle reader, to Rusty's Unreliable Guide to Linux
+   Welcome, gentle reader, to Rusty's Remarkably Unreliable Guide to Linux
    Kernel Hacking.  This document describes the common routines and
    general requirements for kernel code: its goal is to serve as a
    primer for Linux kernel development for experienced C
 
    <listitem>
     <para>
-     not associated with any process, serving a softirq, tasklet or bh;
+     not associated with any process, serving a softirq or tasklet;
     </para>
    </listitem>
 
    <listitem>
     <para>
-     running in kernel space, associated with a process;
+     running in kernel space, associated with a process (user context);
     </para>
    </listitem>
 
   </itemizedlist>
 
   <para>
-   There is a strict ordering between these: other than the last
-   category (userspace) each can only be pre-empted by those above.
-   For example, while a softirq is running on a CPU, no other
-   softirq will pre-empt it, but a hardware interrupt can.  However,
-   any other CPUs in the system execute independently.
+   There is an ordering between these.  The bottom two can preempt
+   each other, but above that is a strict hierarchy: each can only be
+   preempted by the ones above it.  For example, while a softirq is
+   running on a CPU, no other softirq will preempt it, but a hardware
+   interrupt can.  However, any other CPUs in the system execute
+   independently.
   </para>
 
   <para>
    <title>User Context</title>
 
    <para>
-    User context is when you are coming in from a system call or
-    other trap: you can sleep, and you own the CPU (except for
-    interrupts) until you call <function>schedule()</function>.  
-    In other words, user context (unlike userspace) is not pre-emptable.
+    User context is when you are coming in from a system call or other
+    trap: like userspace, you can be preempted by more important tasks
+    and by interrupts.  You can sleep, by calling
+    <function>schedule()</function>.
    </para>
 
    <note>
 
    <caution>
     <para>
-     Beware that if you have interrupts or bottom halves disabled 
+     Beware that if you have preemption or softirqs disabled
      (see below), <function>in_interrupt()</function> will return a 
      false positive.
     </para>
     <hardware>keyboard</hardware> are examples of real
     hardware which produce interrupts at any time.  The kernel runs
     interrupt handlers, which services the hardware.  The kernel
-    guarantees that this handler is never re-entered: if another
+    guarantees that this handler is never re-entered: if the same
     interrupt arrives, it is queued (or dropped).  Because it
     disables interrupts, this handler has to be fast: frequently it
-    simply acknowledges the interrupt, marks a `software interrupt'
+    simply acknowledges the interrupt, marks a 'software interrupt'
     for execution and exits.
    </para>
 
   </sect1>
 
   <sect1 id="basics-softirqs">
-   <title>Software Interrupt Context: Bottom Halves, Tasklets, softirqs</title>
+   <title>Software Interrupt Context: Softirqs and Tasklets</title>
 
    <para>
     Whenever a system call is about to return to userspace, or a
-    hardware interrupt handler exits, any `software interrupts'
+    hardware interrupt handler exits, any 'software interrupts'
     which are marked pending (usually by hardware interrupts) are
     run (<filename>kernel/softirq.c</filename>).
    </para>
 
    <para>
     Much of the real interrupt handling work is done here.  Early in
-    the transition to <acronym>SMP</acronym>, there were only `bottom 
+    the transition to <acronym>SMP</acronym>, there were only 'bottom
     halves' (BHs), which didn't take advantage of multiple CPUs.  Shortly 
     after we switched from wind-up computers made of match-sticks and snot,
-    we abandoned this limitation.
+    we abandoned this limitation and switched to 'softirqs'.
    </para>
 
    <para>
     <filename class="headerfile">include/linux/interrupt.h</filename> lists the
-    different BH's.  No matter how many CPUs you have, no two BHs will run at 
-    the same time. This made the transition to SMP simpler, but sucks hard for
-    scalable performance.  A very important bottom half is the timer
-    BH (<filename class="headerfile">include/linux/timer.h</filename>): you
-    can register to have it call functions for you in a given length of time.
+    different softirqs.  A very important softirq is the
+    timer softirq (<filename
+    class="headerfile">include/linux/timer.h</filename>): you can
+    register to have it call functions for you in a given length of
+    time.
    </para>
 
    <para>
-    2.3.43 introduced softirqs, and re-implemented the (now
-    deprecated) BHs underneath them.  Softirqs are fully-SMP
-    versions of BHs: they can run on as many CPUs at once as
-    required.  This means they need to deal with any races in shared
-    data using their own locks.  A bitmask is used to keep track of
-    which are enabled, so the 32 available softirqs should not be
-    used up lightly.  (<emphasis>Yes</emphasis>, people will
-    notice).
-   </para>
-
-   <para>
-    tasklets (<filename class="headerfile">include/linux/interrupt.h</filename>)
-    are like softirqs, except they are dynamically-registrable (meaning you 
-    can have as many as you want), and they also guarantee that any tasklet 
-    will only run on one CPU at any time, although different tasklets can 
-    run simultaneously (unlike different BHs).  
+    Softirqs are often a pain to deal with, since the same softirq
+    will run simultaneously on more than one CPU.  For this reason,
+    tasklets (<filename
+    class="headerfile">include/linux/interrupt.h</filename>) are more
+    often used: they are dynamically-registrable (meaning you can have
+    as many as you want), and they also guarantee that any tasklet
+    will only run on one CPU at any time, although different tasklets
+    can run simultaneously.
    </para>
    <caution>
     <para>
-     The name `tasklet' is misleading: they have nothing to do with `tasks', 
+     The name 'tasklet' is misleading: they have nothing to do with 'tasks',
      and probably more to do with some bad vodka Alexey Kuznetsov had at the 
      time.
     </para>
    </caution>
 
    <para>
-    You can tell you are in a softirq (or bottom half, or tasklet)
+    You can tell you are in a softirq (or tasklet)
     using the <function>in_softirq()</function> macro 
     (<filename class="headerfile">include/linux/interrupt.h</filename>).
    </para>
     <term>A rigid stack limit</term>
     <listitem>
      <para>
-      The kernel stack is about 6K in 2.2 (for most
-      architectures: it's about 14K on the Alpha), and shared
-      with interrupts so you can't use it all.  Avoid deep
-      recursion and huge local arrays on the stack (allocate
-      them dynamically instead).
+      Depending on configuration options the kernel stack is about 3K to 6K for most 32-bit architectures: it's
+      about 14K on most 64-bit archs, and often shared with interrupts
+      so you can't use it all.  Avoid deep recursion and huge local
+      arrays on the stack (allocate them dynamically instead).
      </para>
     </listitem>
    </varlistentry>
@@ -339,7 +330,7 @@ asmlinkage long sys_mycall(int arg)
 
   <para>
    If all your routine does is read or write some parameter, consider
-   implementing a <function>sysctl</function> interface instead.
+   implementing a <function>sysfs</function> interface instead.
   </para>
 
   <para>
@@ -417,7 +408,10 @@ cond_resched(); /* Will sleep */
   </para>
 
   <para>
-   You will eventually lock up your box if you break these rules.  
+   You should always compile your kernel
+   <symbol>CONFIG_DEBUG_SPINLOCK_SLEEP</symbol> on, and it will warn
+   you if you break these rules.  If you <emphasis>do</emphasis> break
+   the rules, you will eventually lock up your box.
   </para>
 
   <para>
@@ -515,8 +509,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
       success).
      </para>
     </caution>
-    [Yes, this moronic interface makes me cringe.  Please submit a
-    patch and become my hero --RR.]
+    [Yes, this moronic interface makes me cringe.  The flamewar comes up every year or so. --RR.]
    </para>
    <para>
     The functions may sleep implicitly. This should never be called
@@ -587,10 +580,11 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    </variablelist>
 
    <para>
-    If you see a <errorname>kmem_grow: Called nonatomically from int
-    </errorname> warning message you called a memory allocation function
-    from interrupt context without <constant>GFP_ATOMIC</constant>.
-    You should really fix that.  Run, don't walk.
+    If you see a <errorname>sleeping function called from invalid
+    context</errorname> warning message, then maybe you called a
+    sleeping allocation function from interrupt context without
+    <constant>GFP_ATOMIC</constant>.  You should really fix that.
+    Run, don't walk.
    </para>
 
    <para>
@@ -639,16 +633,16 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
   </sect1>
 
   <sect1 id="routines-udelay">
-   <title><function>udelay()</function>/<function>mdelay()</function>
+   <title><function>mdelay()</function>/<function>udelay()</function>
      <filename class="headerfile">include/asm/delay.h</filename>
      <filename class="headerfile">include/linux/delay.h</filename>
    </title>
 
    <para>
-    The <function>udelay()</function> function can be used for small pauses.
-    Do not use large values with <function>udelay()</function> as you risk
+    The <function>udelay()</function> and <function>ndelay()</function> functions can be used for small pauses.
+    Do not use large values with them as you risk
     overflow - the helper function <function>mdelay()</function> is useful
-    here, or even consider <function>schedule_timeout()</function>.
+    here, or consider <function>msleep()</function>.
    </para> 
   </sect1>
  
@@ -698,8 +692,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     These routines disable soft interrupts on the local CPU, and
     restore them.  They are reentrant; if soft interrupts were
     disabled before, they will still be disabled after this pair
-    of functions has been called.  They prevent softirqs, tasklets
-    and bottom halves from running on the current CPU.
+    of functions has been called.  They prevent softirqs and tasklets
+    from running on the current CPU.
    </para>
   </sect1>
 
@@ -708,10 +702,16 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     <filename class="headerfile">include/asm/smp.h</filename></title>
    
    <para>
-    <function>smp_processor_id()</function> returns the current
-    processor number, between 0 and <symbol>NR_CPUS</symbol> (the
-    maximum number of CPUs supported by Linux, currently 32).  These
-    values are not necessarily continuous.
+    <function>get_cpu()</function> disables preemption (so you won't
+    suddenly get moved to another CPU) and returns the current
+    processor number, between 0 and <symbol>NR_CPUS</symbol>.  Note
+    that the CPU numbers are not necessarily continuous.  You return
+    it again with <function>put_cpu()</function> when you are done.
+   </para>
+   <para>
+    If you know you cannot be preempted by another task (ie. you are
+    in interrupt context, or have preemption disabled) you can use
+    smp_processor_id().
    </para>
   </sect1>
 
@@ -722,19 +722,14 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    <para>
     After boot, the kernel frees up a special section; functions
     marked with <type>__init</type> and data structures marked with
-    <type>__initdata</type> are dropped after boot is complete (within
-    modules this directive is currently ignored).  <type>__exit</type>
+    <type>__initdata</type> are dropped after boot is complete: similarly
+    modules discard this memory after initialization.  <type>__exit</type>
     is used to declare a function which is only required on exit: the
     function will be dropped if this file is not compiled as a module.
     See the header file for use. Note that it makes no sense for a function
     marked with <type>__init</type> to be exported to modules with 
     <function>EXPORT_SYMBOL()</function> - this will break.
    </para>
-   <para>
-   Static data structures marked as <type>__initdata</type> must be initialised
-   (as opposed to ordinary static data which is zeroed BSS) and cannot be 
-   <type>const</type>.
-   </para> 
 
   </sect1>
 
@@ -762,9 +757,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    <para>
     The function can return a negative error number to cause
     module loading to fail (unfortunately, this has no effect if
-    the module is compiled into the kernel).  For modules, this is
-    called in user context, with interrupts enabled, and the
-    kernel lock held, so it can sleep.
+    the module is compiled into the kernel).  This function is
+    called in user context with interrupts enabled, so it can sleep.
    </para>
   </sect1>
   
@@ -779,6 +773,34 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     reached zero.  This function can also sleep, but cannot fail:
     everything must be cleaned up by the time it returns.
    </para>
+
+   <para>
+    Note that this macro is optional: if it is not present, your
+    module will not be removable (except for 'rmmod -f').
+   </para>
+  </sect1>
+
+  <sect1 id="routines-module-use-counters">
+   <title> <function>try_module_get()</function>/<function>module_put()</function>
+    <filename class="headerfile">include/linux/module.h</filename></title>
+
+   <para>
+    These manipulate the module usage count, to protect against
+    removal (a module also can't be removed if another module uses one
+    of its exported symbols: see below).  Before calling into module
+    code, you should call <function>try_module_get()</function> on
+    that module: if it fails, then the module is being removed and you
+    should act as if it wasn't there.  Otherwise, you can safely enter
+    the module, and call <function>module_put()</function> when you're
+    finished.
+   </para>
+
+   <para>
+   Most registerable structures have an
+   <structfield>owner</structfield> field, such as in the
+   <structname>file_operations</structname> structure. Set this field
+   to the macro <symbol>THIS_MODULE</symbol>.
+   </para>
   </sect1>
 
  <!-- add info on new-style module refcounting here -->
@@ -821,7 +843,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     There is a macro to do this:
     <function>wait_event_interruptible()</function>
 
-    <filename class="headerfile">include/linux/sched.h</filename> The
+    <filename class="headerfile">include/linux/wait.h</filename> The
     first argument is the wait queue head, and the second is an
     expression which is evaluated; the macro returns
     <returnvalue>0</returnvalue> when this expression is true, or
@@ -847,10 +869,11 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    <para>
     Call <function>wake_up()</function>
 
-    <filename class="headerfile">include/linux/sched.h</filename>;,
+    <filename class="headerfile">include/linux/wait.h</filename>;,
     which will wake up every process in the queue.  The exception is
     if one has <constant>TASK_EXCLUSIVE</constant> set, in which case
-    the remainder of the queue will not be woken.
+    the remainder of the queue will not be woken.  There are other variants
+    of this basic function available in the same header.
    </para>
   </sect1>
  </chapter>
@@ -863,7 +886,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    first class of operations work on <type>atomic_t</type>
 
    <filename class="headerfile">include/asm/atomic.h</filename>; this
-   contains a signed integer (at least 24 bits long), and you must use
+   contains a signed integer (at least 32 bits long), and you must use
    these functions to manipulate or read atomic_t variables.
    <function>atomic_read()</function> and
    <function>atomic_set()</function> get and set the counter,
@@ -882,13 +905,12 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
 
   <para>
    Note that these functions are slower than normal arithmetic, and
-   so should not be used unnecessarily.  On some platforms they
-   are much slower, like 32-bit Sparc where they use a spinlock.
+   so should not be used unnecessarily.
   </para>
 
   <para>
-   The second class of atomic operations is atomic bit operations on a
-   <type>long</type>, defined in
+   The second class of atomic operations is atomic bit operations on an
+   <type>unsigned long</type>, defined in
 
    <filename class="headerfile">include/linux/bitops.h</filename>.  These
    operations generally take a pointer to the bit pattern, and a bit
@@ -899,7 +921,7 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    <function>test_and_clear_bit()</function> and
    <function>test_and_change_bit()</function> do the same thing,
    except return true if the bit was previously set; these are
-   particularly useful for very simple locking.
+   particularly useful for atomically setting flags.
   </para>
   
   <para>
@@ -907,12 +929,6 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
    than BITS_PER_LONG.  The resulting behavior is strange on big-endian
    platforms though so it is a good idea not to do this.
   </para>
-
-  <para>
-   Note that the order of bits depends on the architecture, and in
-   particular, the bitfield passed to these operations must be at
-   least as large as a <type>long</type>.
-  </para>
  </chapter>
 
  <chapter id="symbols">
@@ -932,11 +948,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     <filename class="headerfile">include/linux/module.h</filename></title>
 
    <para>
-    This is the classic method of exporting a symbol, and it works
-    for both modules and non-modules.  In the kernel all these
-    declarations are often bundled into a single file to help
-    genksyms (which searches source files for these declarations).
-    See the comment on genksyms and Makefiles below.
+    This is the classic method of exporting a symbol: dynamically
+    loaded modules will be able to use the symbol as normal.
    </para>
   </sect1>
 
@@ -949,7 +962,8 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     symbols exported by <function>EXPORT_SYMBOL_GPL()</function> can
     only be seen by modules with a
     <function>MODULE_LICENSE()</function> that specifies a GPL
-    compatible license.
+    compatible license.  It implies that the function is considered
+    an internal implementation issue, and not really an interface.
    </para>
   </sect1>
  </chapter>
@@ -962,12 +976,13 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     <filename class="headerfile">include/linux/list.h</filename></title>
 
    <para>
-    There are three sets of linked-list routines in the kernel
-    headers, but this one seems to be winning out (and Linus has
-    used it).  If you don't have some particular pressing need for
-    a single list, it's a good choice.  In fact, I don't care
-    whether it's a good choice or not, just use it so we can get
-    rid of the others.
+    There used to be three sets of linked-list routines in the kernel
+    headers, but this one is the winner.  If you don't have some
+    particular pressing need for a single list, it's a good choice.
+   </para>
+
+   <para>
+    In particular, <function>list_for_each_entry</function> is useful.
    </para>
   </sect1>
 
@@ -979,14 +994,13 @@ printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
     convention, and return <returnvalue>0</returnvalue> for success,
     and a negative error number
     (eg. <returnvalue>-EFAULT</returnvalue>) for failure.  This can be
-    unintuitive at first, but it's fairly widespread in the networking
-    code, for example.
+    unintuitive at first, but it's fairly widespread in the kernel.
    </para>
 
    <para>
-    The filesystem code uses <function>ERR_PTR()</function>
+    Using <function>ERR_PTR()</function>
 
-    <filename class="headerfile">include/linux/fs.h</filename>; to
+    <filename class="headerfile">include/linux/err.h</filename>; to
     encode a negative error number into a pointer, and
     <function>IS_ERR()</function> and <function>PTR_ERR()</function>
     to get it back out again: avoids a separate pointer parameter for
@@ -1040,7 +1054,7 @@ static struct block_device_operations opt_fops = {
     supported, due to lack of general use, but the following are
     considered standard (see the GCC info page section "C
     Extensions" for more details - Yes, really the info page, the
-    man page is only a short summary of the stuff in info):
+    man page is only a short summary of the stuff in info).
    </para>
    <itemizedlist>
     <listitem>
@@ -1091,7 +1105,7 @@ static struct block_device_operations opt_fops = {
     </listitem>
     <listitem>
      <para>
-      Function names as strings (__FUNCTION__)
+      Function names as strings (__func__).
      </para>
     </listitem>
     <listitem>
@@ -1164,63 +1178,35 @@ static struct block_device_operations opt_fops = {
    <listitem>
     <para>
      Usually you want a configuration option for your kernel hack.
-     Edit <filename>Config.in</filename> in the appropriate directory
-     (but under <filename>arch/</filename> it's called
-     <filename>config.in</filename>).  The Config Language used is not
-     bash, even though it looks like bash; the safe way is to use only
-     the constructs that you already see in
-     <filename>Config.in</filename> files (see
-     <filename>Documentation/kbuild/kconfig-language.txt</filename>).
-     It's good to run "make xconfig" at least once to test (because
-     it's the only one with a static parser).
-    </para>
-
-    <para>
-     Variables which can be Y or N use <type>bool</type> followed by a
-     tagline and the config define name (which must start with
-     CONFIG_).  The <type>tristate</type> function is the same, but
-     allows the answer M (which defines
-     <symbol>CONFIG_foo_MODULE</symbol> in your source, instead of
-     <symbol>CONFIG_FOO</symbol>) if <symbol>CONFIG_MODULES</symbol>
-     is enabled.
+     Edit <filename>Kconfig</filename> in the appropriate directory.
+     The Config language is simple to use by cut and paste, and there's
+     complete documentation in
+     <filename>Documentation/kbuild/kconfig-language.txt</filename>.
     </para>
 
     <para>
      You may well want to make your CONFIG option only visible if
      <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a
      warning to users.  There many other fancy things you can do: see
-     the various <filename>Config.in</filename> files for ideas.
+     the various <filename>Kconfig</filename> files for ideas.
     </para>
-   </listitem>
 
-   <listitem>
     <para>
-     Edit the <filename>Makefile</filename>: the CONFIG variables are
-     exported here so you can conditionalize compilation with `ifeq'.
-     If your file exports symbols then add the names to
-     <varname>export-objs</varname> so that genksyms will find them.
-     <caution>
-      <para>
-       There is a restriction on the kernel build system that objects
-       which export symbols must have globally unique names.
-       If your object does not have a globally unique name then the
-       standard fix is to move the
-       <function>EXPORT_SYMBOL()</function> statements to their own
-       object with a unique name.
-       This is why several systems have separate exporting objects,
-       usually suffixed with ksyms.
-      </para>
-     </caution>
+     In your description of the option, make sure you address both the
+     expert user and the user who knows nothing about your feature.  Mention
+     incompatibilities and issues here.  <emphasis> Definitely
+     </emphasis> end your description with <quote> if in doubt, say N
+     </quote> (or, occasionally, `Y'); this is for people who have no
+     idea what you are talking about.
     </para>
    </listitem>
 
    <listitem>
     <para>
-     Document your option in Documentation/Configure.help.  Mention
-     incompatibilities and issues here.  <emphasis> Definitely
-     </emphasis> end your description with <quote> if in doubt, say N
-     </quote> (or, occasionally, `Y'); this is for people who have no
-     idea what you are talking about.
+     Edit the <filename>Makefile</filename>: the CONFIG variables are
+     exported here so you can usually just add a "obj-$(CONFIG_xxx) +=
+     xxx.o" line.  The syntax is documented in
+     <filename>Documentation/kbuild/makefiles.txt</filename>.
     </para>
    </listitem>
 
@@ -1253,20 +1239,12 @@ static struct block_device_operations opt_fops = {
   </para>
 
   <para>
-   <filename>include/linux/brlock.h:</filename>
+   <filename>include/asm-i386/delay.h:</filename>
   </para>
   <programlisting>
-extern inline void br_read_lock (enum brlock_indices idx)
-{
-        /*
-         * This causes a link-time bug message if an
-         * invalid index is used:
-         */
-        if (idx >= __BR_END)
-                __br_lock_usage_bug();
-
-        read_lock(&amp;__brlock_array[smp_processor_id()][idx]);
-}
+#define ndelay(n) (__builtin_constant_p(n) ? \
+        ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+        __ndelay(n))
   </programlisting>
 
   <para>
index f3ef0bf435e9ebde6ba5174f43ef7168059058fa..705c442c7bf4cfcd687ea84aa92e6713463f6fcb 100644 (file)
@@ -841,7 +841,7 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
                    File modification time is not updated by this request.
                    </para><para>
                    Those struct members are from some interface descriptor
-                   applying to the the current configuration.
+                   applying to the current configuration.
                    The interface number is the bInterfaceNumber value, and
                    the altsetting number is the bAlternateSetting value.
                    (This resets each endpoint in the interface.)
index d5032eb480aa364593d73bd6f211ec23bc2b990e..63edc5f847c45a4b1771c4e35872317ca2bbcbc7 100644 (file)
@@ -430,7 +430,7 @@ which may result in system hang. The software driver of specific
 MSI-capable hardware is responsible for whether calling
 pci_enable_msi or not. A return of zero indicates the kernel
 successfully initializes the MSI/MSI-X capability structure of the
-device funtion. The device function is now running on MSI/MSI-X mode.
+device function. The device function is now running on MSI/MSI-X mode.
 
 5.6 How to tell whether MSI/MSI-X is enabled on device function
 
index 9c6d450138ead56f9f1ef4c2e55794b2b30ff77c..fcbcbc35b122fda0223e22c267f7bca240e48b5b 100644 (file)
@@ -2,7 +2,8 @@ Read the F-ing Papers!
 
 
 This document describes RCU-related publications, and is followed by
-the corresponding bibtex entries.
+the corresponding bibtex entries.  A number of the publications may
+be found at http://www.rdrop.com/users/paulmck/RCU/.
 
 The first thing resembling RCU was published in 1980, when Kung and Lehman
 [Kung80] recommended use of a garbage collector to defer destruction
@@ -113,6 +114,10 @@ describing how to make RCU safe for soft-realtime applications [Sarma04c],
 and a paper describing SELinux performance with RCU [JamesMorris04b].
 
 
+2005 has seen further adaptation of RCU to realtime use, permitting
+preemption of RCU realtime critical sections [PaulMcKenney05a,
+PaulMcKenney05b].
+
 Bibtex Entries
 
 @article{Kung80
@@ -410,3 +415,32 @@ Oregon Health and Sciences University"
 \url{http://www.livejournal.com/users/james_morris/2153.html}
 [Viewed December 10, 2004]"
 }
+
+@unpublished{PaulMcKenney05a
+,Author="Paul E. McKenney"
+,Title="{[RFC]} {RCU} and {CONFIG\_PREEMPT\_RT} progress"
+,month="May"
+,year="2005"
+,note="Available:
+\url{http://lkml.org/lkml/2005/5/9/185}
+[Viewed May 13, 2005]"
+,annotation="
+       First publication of working lock-based deferred free patches
+       for the CONFIG_PREEMPT_RT environment.
+"
+}
+
+@conference{PaulMcKenney05b
+,Author="Paul E. McKenney and Dipankar Sarma"
+,Title="Towards Hard Realtime Response from the Linux Kernel on SMP Hardware"
+,Booktitle="linux.conf.au 2005"
+,month="April"
+,year="2005"
+,address="Canberra, Australia"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/realtimeRCU.2005.04.23a.pdf}
+[Viewed May 13, 2005]"
+,annotation="
+       Realtime turns into making RCU yet more realtime friendly.
+"
+}
index 3bfb84b3b7dbc5120bbcbf14c52ed95fb2a72507..aab4a9ec3931520554a76b2e33e5096b5a0ca632 100644 (file)
@@ -8,7 +8,7 @@ is that since there is only one CPU, it should not be necessary to
 wait for anything else to get done, since there are no other CPUs for
 anything else to be happening on.  Although this approach will -sort- -of-
 work a surprising amount of the time, it is a very bad idea in general.
-This document presents two examples that demonstrate exactly how bad an
+This document presents three examples that demonstrate exactly how bad an
 idea this is.
 
 
@@ -26,6 +26,9 @@ from softirq, the list scan would find itself referencing a newly freed
 element B.  This situation can greatly decrease the life expectancy of
 your kernel.
 
+This same problem can occur if call_rcu() is invoked from a hardware
+interrupt handler.
+
 
 Example 2: Function-Call Fatality
 
@@ -44,8 +47,37 @@ its arguments would cause it to fail to make the fundamental guarantee
 underlying RCU, namely that call_rcu() defers invoking its arguments until
 all RCU read-side critical sections currently executing have completed.
 
-Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in
-this case?
+Quick Quiz #1: why is it -not- legal to invoke synchronize_rcu() in
+       this case?
+
+
+Example 3: Death by Deadlock
+
+Suppose that call_rcu() is invoked while holding a lock, and that the
+callback function must acquire this same lock.  In this case, if
+call_rcu() were to directly invoke the callback, the result would
+be self-deadlock.
+
+In some cases, it would possible to restructure to code so that
+the call_rcu() is delayed until after the lock is released.  However,
+there are cases where this can be quite ugly:
+
+1.     If a number of items need to be passed to call_rcu() within
+       the same critical section, then the code would need to create
+       a list of them, then traverse the list once the lock was
+       released.
+
+2.     In some cases, the lock will be held across some kernel API,
+       so that delaying the call_rcu() until the lock is released
+       requires that the data item be passed up via a common API.
+       It is far better to guarantee that callbacks are invoked
+       with no locks held than to have to modify such APIs to allow
+       arbitrary data items to be passed back up through them.
+
+If call_rcu() directly invokes the callback, painful locking restrictions
+or API changes would be required.
+
+Quick Quiz #2: What locking restriction must RCU callbacks respect?
 
 
 Summary
@@ -53,12 +85,35 @@ Summary
 Permitting call_rcu() to immediately invoke its arguments or permitting
 synchronize_rcu() to immediately return breaks RCU, even on a UP system.
 So do not do it!  Even on a UP system, the RCU infrastructure -must-
-respect grace periods.
-
-
-Answer to Quick Quiz
-
-The calling function is scanning an RCU-protected linked list, and
-is therefore within an RCU read-side critical section.  Therefore,
-the called function has been invoked within an RCU read-side critical
-section, and is not permitted to block.
+respect grace periods, and -must- invoke callbacks from a known environment
+in which no locks are held.
+
+
+Answer to Quick Quiz #1:
+       Why is it -not- legal to invoke synchronize_rcu() in this case?
+
+       Because the calling function is scanning an RCU-protected linked
+       list, and is therefore within an RCU read-side critical section.
+       Therefore, the called function has been invoked within an RCU
+       read-side critical section, and is not permitted to block.
+
+Answer to Quick Quiz #2:
+       What locking restriction must RCU callbacks respect?
+
+       Any lock that is acquired within an RCU callback must be
+       acquired elsewhere using an _irq variant of the spinlock
+       primitive.  For example, if "mylock" is acquired by an
+       RCU callback, then a process-context acquisition of this
+       lock must use something like spin_lock_irqsave() to
+       acquire the lock.
+
+       If the process-context code were to simply use spin_lock(),
+       then, since RCU callbacks can be invoked from softirq context,
+       the callback might be called from a softirq that interrupted
+       the process-context critical section.  This would result in
+       self-deadlock.
+
+       This restriction might seem gratuitous, since very few RCU
+       callbacks acquire locks directly.  However, a great many RCU
+       callbacks do acquire locks -indirectly-, for example, via
+       the kfree() primitive.
index 8f3fb77c9cd32f2732351c2a78701110d2fc2454..e118a7c1a0928d9aadc5f4cd34d4e110a930a1ee 100644 (file)
@@ -43,6 +43,10 @@ over a rather long period of time, but improvements are always welcome!
        rcu_read_lock_bh()) in the read-side critical sections,
        and are also an excellent aid to readability.
 
+       As a rough rule of thumb, any dereference of an RCU-protected
+       pointer must be covered by rcu_read_lock() or rcu_read_lock_bh()
+       or by the appropriate update-side lock.
+
 3.     Does the update code tolerate concurrent accesses?
 
        The whole point of RCU is to permit readers to run without
@@ -90,7 +94,11 @@ over a rather long period of time, but improvements are always welcome!
 
                The rcu_dereference() primitive is used by the various
                "_rcu()" list-traversal primitives, such as the
-               list_for_each_entry_rcu().
+               list_for_each_entry_rcu().  Note that it is perfectly
+               legal (if redundant) for update-side code to use
+               rcu_dereference() and the "_rcu()" list-traversal
+               primitives.  This is particularly useful in code
+               that is common to readers and updaters.
 
        b.      If the list macros are being used, the list_add_tail_rcu()
                and list_add_rcu() primitives must be used in order
@@ -150,16 +158,9 @@ over a rather long period of time, but improvements are always welcome!
 
        Use of the _rcu() list-traversal primitives outside of an
        RCU read-side critical section causes no harm other than
-       a slight performance degradation on Alpha CPUs and some
-       confusion on the part of people trying to read the code.
-
-       Another way of thinking of this is "If you are holding the
-       lock that prevents the data structure from changing, why do
-       you also need RCU-based protection?"  That said, there may
-       well be situations where use of the _rcu() list-traversal
-       primitives while the update-side lock is held results in
-       simpler and more maintainable code.  The jury is still out
-       on this question.
+       a slight performance degradation on Alpha CPUs.  It can
+       also be quite helpful in reducing code bloat when common
+       code is shared between readers and updaters.
 
 10.    Conversely, if you are in an RCU read-side critical section,
        you -must- use the "_rcu()" variants of the list macros.
index eb444006683e28140cc0c1eb6d02f74f6f344503..6fa092251586e14930c6d51d8bde1d4566512138 100644 (file)
@@ -64,6 +64,54 @@ o    I hear that RCU is patented?  What is with that?
        Of these, one was allowed to lapse by the assignee, and the
        others have been contributed to the Linux kernel under GPL.
 
+o      I hear that RCU needs work in order to support realtime kernels?
+
+       Yes, work in progress.
+
 o      Where can I find more information on RCU?
 
        See the RTFP.txt file in this directory.
+       Or point your browser at http://www.rdrop.com/users/paulmck/RCU/.
+
+o      What are all these files in this directory?
+
+
+       NMI-RCU.txt
+
+               Describes how to use RCU to implement dynamic
+               NMI handlers, which can be revectored on the fly,
+               without rebooting.
+
+       RTFP.txt
+
+               List of RCU-related publications and web sites.
+
+       UP.txt
+
+               Discussion of RCU usage in UP kernels.
+
+       arrayRCU.txt
+
+               Describes how to use RCU to protect arrays, with
+               resizeable arrays whose elements reference other
+               data structures being of the most interest.
+
+       checklist.txt
+
+               Lists things to check for when inspecting code that
+               uses RCU.
+
+       listRCU.txt
+
+               Describes how to use RCU to protect linked lists.
+               This is the simplest and most common use of RCU
+               in the Linux kernel.
+
+       rcu.txt
+
+               You are reading it!
+
+       whatisRCU.txt
+
+               Overview of how the RCU implementation works.  Along
+               the way, presents a conceptual view of RCU.
diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt
new file mode 100644 (file)
index 0000000..a23fee6
--- /dev/null
@@ -0,0 +1,74 @@
+Refcounter framework for elements of lists/arrays protected by
+RCU.
+
+Refcounting on elements of  lists which are protected by traditional
+reader/writer spinlocks or semaphores are straight forward as in:
+
+1.                                     2.
+add()                                  search_and_reference()
+{                                      {
+       alloc_object                            read_lock(&list_lock);
+       ...                                     search_for_element
+       atomic_set(&el->rc, 1);                 atomic_inc(&el->rc);
+       write_lock(&list_lock);                 ...
+       add_element                             read_unlock(&list_lock);
+       ...                                     ...
+       write_unlock(&list_lock);       }
+}
+
+3.                                     4.
+release_referenced()                   delete()
+{                                      {
+       ...                             write_lock(&list_lock);
+       atomic_dec(&el->rc, relfunc)    ...
+       ...                             delete_element
+}                                      write_unlock(&list_lock);
+                                       ...
+                                       if (atomic_dec_and_test(&el->rc))
+                                               kfree(el);
+                                       ...
+                                       }
+
+If this list/array is made lock free using rcu as in changing the
+write_lock in add() and delete() to spin_lock and changing read_lock
+in search_and_reference to rcu_read_lock(), the rcuref_get in
+search_and_reference could potentially hold reference to an element which
+has already been deleted from the list/array.  rcuref_lf_get_rcu takes
+care of this scenario. search_and_reference should look as;
+
+1.                                     2.
+add()                                  search_and_reference()
+{                                      {
+       alloc_object                            rcu_read_lock();
+       ...                                     search_for_element
+       atomic_set(&el->rc, 1);                 if (rcuref_inc_lf(&el->rc)) {
+       write_lock(&list_lock);                         rcu_read_unlock();
+                                                       return FAIL;
+       add_element                             }
+       ...                                     ...
+       write_unlock(&list_lock);               rcu_read_unlock();
+}                                      }
+3.                                     4.
+release_referenced()                   delete()
+{                                      {
+       ...                             write_lock(&list_lock);
+       rcuref_dec(&el->rc, relfunc)    ...
+       ...                             delete_element
+}                                      write_unlock(&list_lock);
+                                       ...
+                                       if (rcuref_dec_and_test(&el->rc))
+                                               call_rcu(&el->head, el_free);
+                                       ...
+                                       }
+
+Sometimes, reference to the element need to be obtained in the
+update (write) stream.  In such cases, rcuref_inc_lf might be an overkill
+since the spinlock serialising list updates are held. rcuref_inc
+is to be used in such cases.
+For arches which do not have cmpxchg rcuref_inc_lf
+api uses a hashed spinlock implementation and the same hashed spinlock
+is acquired in all rcuref_xxx primitives to preserve atomicity.
+Note: Use rcuref_inc api only if you need to use rcuref_inc_lf on the
+refcounter atleast at one place.  Mixing rcuref_inc and atomic_xxx api
+might lead to races. rcuref_inc_lf() must be used in lockfree
+RCU critical sections only.
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
new file mode 100644 (file)
index 0000000..354d89c
--- /dev/null
@@ -0,0 +1,902 @@
+What is RCU?
+
+RCU is a synchronization mechanism that was added to the Linux kernel
+during the 2.5 development effort that is optimized for read-mostly
+situations.  Although RCU is actually quite simple once you understand it,
+getting there can sometimes be a challenge.  Part of the problem is that
+most of the past descriptions of RCU have been written with the mistaken
+assumption that there is "one true way" to describe RCU.  Instead,
+the experience has been that different people must take different paths
+to arrive at an understanding of RCU.  This document provides several
+different paths, as follows:
+
+1.     RCU OVERVIEW
+2.     WHAT IS RCU'S CORE API?
+3.     WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
+4.     WHAT IF MY UPDATING THREAD CANNOT BLOCK?
+5.     WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU?
+6.     ANALOGY WITH READER-WRITER LOCKING
+7.     FULL LIST OF RCU APIs
+8.     ANSWERS TO QUICK QUIZZES
+
+People who prefer starting with a conceptual overview should focus on
+Section 1, though most readers will profit by reading this section at
+some point.  People who prefer to start with an API that they can then
+experiment with should focus on Section 2.  People who prefer to start
+with example uses should focus on Sections 3 and 4.  People who need to
+understand the RCU implementation should focus on Section 5, then dive
+into the kernel source code.  People who reason best by analogy should
+focus on Section 6.  Section 7 serves as an index to the docbook API
+documentation, and Section 8 is the traditional answer key.
+
+So, start with the section that makes the most sense to you and your
+preferred method of learning.  If you need to know everything about
+everything, feel free to read the whole thing -- but if you are really
+that type of person, you have perused the source code and will therefore
+never need this document anyway.  ;-)
+
+
+1.  RCU OVERVIEW
+
+The basic idea behind RCU is to split updates into "removal" and
+"reclamation" phases.  The removal phase removes references to data items
+within a data structure (possibly by replacing them with references to
+new versions of these data items), and can run concurrently with readers.
+The reason that it is safe to run the removal phase concurrently with
+readers is the semantics of modern CPUs guarantee that readers will see
+either the old or the new version of the data structure rather than a
+partially updated reference.  The reclamation phase does the work of reclaiming
+(e.g., freeing) the data items removed from the data structure during the
+removal phase.  Because reclaiming data items can disrupt any readers
+concurrently referencing those data items, the reclamation phase must
+not start until readers no longer hold references to those data items.
+
+Splitting the update into removal and reclamation phases permits the
+updater to perform the removal phase immediately, and to defer the
+reclamation phase until all readers active during the removal phase have
+completed, either by blocking until they finish or by registering a
+callback that is invoked after they finish.  Only readers that are active
+during the removal phase need be considered, because any reader starting
+after the removal phase will be unable to gain a reference to the removed
+data items, and therefore cannot be disrupted by the reclamation phase.
+
+So the typical RCU update sequence goes something like the following:
+
+a.     Remove pointers to a data structure, so that subsequent
+       readers cannot gain a reference to it.
+
+b.     Wait for all previous readers to complete their RCU read-side
+       critical sections.
+
+c.     At this point, there cannot be any readers who hold references
+       to the data structure, so it now may safely be reclaimed
+       (e.g., kfree()d).
+
+Step (b) above is the key idea underlying RCU's deferred destruction.
+The ability to wait until all readers are done allows RCU readers to
+use much lighter-weight synchronization, in some cases, absolutely no
+synchronization at all.  In contrast, in more conventional lock-based
+schemes, readers must use heavy-weight synchronization in order to
+prevent an updater from deleting the data structure out from under them.
+This is because lock-based updaters typically update data items in place,
+and must therefore exclude readers.  In contrast, RCU-based updaters
+typically take advantage of the fact that writes to single aligned
+pointers are atomic on modern CPUs, allowing atomic insertion, removal,
+and replacement of data items in a linked structure without disrupting
+readers.  Concurrent RCU readers can then continue accessing the old
+versions, and can dispense with the atomic operations, memory barriers,
+and communications cache misses that are so expensive on present-day
+SMP computer systems, even in absence of lock contention.
+
+In the three-step procedure shown above, the updater is performing both
+the removal and the reclamation step, but it is often helpful for an
+entirely different thread to do the reclamation, as is in fact the case
+in the Linux kernel's directory-entry cache (dcache).  Even if the same
+thread performs both the update step (step (a) above) and the reclamation
+step (step (c) above), it is often helpful to think of them separately.
+For example, RCU readers and updaters need not communicate at all,
+but RCU provides implicit low-overhead communication between readers
+and reclaimers, namely, in step (b) above.
+
+So how the heck can a reclaimer tell when a reader is done, given
+that readers are not doing any sort of synchronization operations???
+Read on to learn about how RCU's API makes this easy.
+
+
+2.  WHAT IS RCU'S CORE API?
+
+The core RCU API is quite small:
+
+a.     rcu_read_lock()
+b.     rcu_read_unlock()
+c.     synchronize_rcu() / call_rcu()
+d.     rcu_assign_pointer()
+e.     rcu_dereference()
+
+There are many other members of the RCU API, but the rest can be
+expressed in terms of these five, though most implementations instead
+express synchronize_rcu() in terms of the call_rcu() callback API.
+
+The five core RCU APIs are described below, the other 18 will be enumerated
+later.  See the kernel docbook documentation for more info, or look directly
+at the function header comments.
+
+rcu_read_lock()
+
+       void rcu_read_lock(void);
+
+       Used by a reader to inform the reclaimer that the reader is
+       entering an RCU read-side critical section.  It is illegal
+       to block while in an RCU read-side critical section, though
+       kernels built with CONFIG_PREEMPT_RCU can preempt RCU read-side
+       critical sections.  Any RCU-protected data structure accessed
+       during an RCU read-side critical section is guaranteed to remain
+       unreclaimed for the full duration of that critical section.
+       Reference counts may be used in conjunction with RCU to maintain
+       longer-term references to data structures.
+
+rcu_read_unlock()
+
+       void rcu_read_unlock(void);
+
+       Used by a reader to inform the reclaimer that the reader is
+       exiting an RCU read-side critical section.  Note that RCU
+       read-side critical sections may be nested and/or overlapping.
+
+synchronize_rcu()
+
+       void synchronize_rcu(void);
+
+       Marks the end of updater code and the beginning of reclaimer
+       code.  It does this by blocking until all pre-existing RCU
+       read-side critical sections on all CPUs have completed.
+       Note that synchronize_rcu() will -not- necessarily wait for
+       any subsequent RCU read-side critical sections to complete.
+       For example, consider the following sequence of events:
+
+                CPU 0                  CPU 1                 CPU 2
+            ----------------- ------------------------- ---------------
+        1.  rcu_read_lock()
+        2.                    enters synchronize_rcu()
+        3.                                               rcu_read_lock()
+        4.  rcu_read_unlock()
+        5.                     exits synchronize_rcu()
+        6.                                              rcu_read_unlock()
+
+       To reiterate, synchronize_rcu() waits only for ongoing RCU
+       read-side critical sections to complete, not necessarily for
+       any that begin after synchronize_rcu() is invoked.
+
+       Of course, synchronize_rcu() does not necessarily return
+       -immediately- after the last pre-existing RCU read-side critical
+       section completes.  For one thing, there might well be scheduling
+       delays.  For another thing, many RCU implementations process
+       requests in batches in order to improve efficiencies, which can
+       further delay synchronize_rcu().
+
+       Since synchronize_rcu() is the API that must figure out when
+       readers are done, its implementation is key to RCU.  For RCU
+       to be useful in all but the most read-intensive situations,
+       synchronize_rcu()'s overhead must also be quite small.
+
+       The call_rcu() API is a callback form of synchronize_rcu(),
+       and is described in more detail in a later section.  Instead of
+       blocking, it registers a function and argument which are invoked
+       after all ongoing RCU read-side critical sections have completed.
+       This callback variant is particularly useful in situations where
+       it is illegal to block.
+
+rcu_assign_pointer()
+
+       typeof(p) rcu_assign_pointer(p, typeof(p) v);
+
+       Yes, rcu_assign_pointer() -is- implemented as a macro, though it
+       would be cool to be able to declare a function in this manner.
+       (Compiler experts will no doubt disagree.)
+
+       The updater uses this function to assign a new value to an
+       RCU-protected pointer, in order to safely communicate the change
+       in value from the updater to the reader.  This function returns
+       the new value, and also executes any memory-barrier instructions
+       required for a given CPU architecture.
+
+       Perhaps more important, it serves to document which pointers
+       are protected by RCU.  That said, rcu_assign_pointer() is most
+       frequently used indirectly, via the _rcu list-manipulation
+       primitives such as list_add_rcu().
+
+rcu_dereference()
+
+       typeof(p) rcu_dereference(p);
+
+       Like rcu_assign_pointer(), rcu_dereference() must be implemented
+       as a macro.
+
+       The reader uses rcu_dereference() to fetch an RCU-protected
+       pointer, which returns a value that may then be safely
+       dereferenced.  Note that rcu_deference() does not actually
+       dereference the pointer, instead, it protects the pointer for
+       later dereferencing.  It also executes any needed memory-barrier
+       instructions for a given CPU architecture.  Currently, only Alpha
+       needs memory barriers within rcu_dereference() -- on other CPUs,
+       it compiles to nothing, not even a compiler directive.
+
+       Common coding practice uses rcu_dereference() to copy an
+       RCU-protected pointer to a local variable, then dereferences
+       this local variable, for example as follows:
+
+               p = rcu_dereference(head.next);
+               return p->data;
+
+       However, in this case, one could just as easily combine these
+       into one statement:
+
+               return rcu_dereference(head.next)->data;
+
+       If you are going to be fetching multiple fields from the
+       RCU-protected structure, using the local variable is of
+       course preferred.  Repeated rcu_dereference() calls look
+       ugly and incur unnecessary overhead on Alpha CPUs.
+
+       Note that the value returned by rcu_dereference() is valid
+       only within the enclosing RCU read-side critical section.
+       For example, the following is -not- legal:
+
+               rcu_read_lock();
+               p = rcu_dereference(head.next);
+               rcu_read_unlock();
+               x = p->address;
+               rcu_read_lock();
+               y = p->data;
+               rcu_read_unlock();
+
+       Holding a reference from one RCU read-side critical section
+       to another is just as illegal as holding a reference from
+       one lock-based critical section to another!  Similarly,
+       using a reference outside of the critical section in which
+       it was acquired is just as illegal as doing so with normal
+       locking.
+
+       As with rcu_assign_pointer(), an important function of
+       rcu_dereference() is to document which pointers are protected
+       by RCU.  And, again like rcu_assign_pointer(), rcu_dereference()
+       is typically used indirectly, via the _rcu list-manipulation
+       primitives, such as list_for_each_entry_rcu().
+
+The following diagram shows how each API communicates among the
+reader, updater, and reclaimer.
+
+
+           rcu_assign_pointer()
+                                   +--------+
+           +---------------------->| reader |---------+
+           |                       +--------+         |
+           |                           |              |
+           |                           |              | Protect:
+           |                           |              | rcu_read_lock()
+           |                           |              | rcu_read_unlock()
+           |        rcu_dereference()  |              |
+       +---------+                      |              |
+       | updater |<---------------------+              |
+       +---------+                                     V
+           |                                    +-----------+
+           +----------------------------------->| reclaimer |
+                                                +-----------+
+             Defer:
+             synchronize_rcu() & call_rcu()
+
+
+The RCU infrastructure observes the time sequence of rcu_read_lock(),
+rcu_read_unlock(), synchronize_rcu(), and call_rcu() invocations in
+order to determine when (1) synchronize_rcu() invocations may return
+to their callers and (2) call_rcu() callbacks may be invoked.  Efficient
+implementations of the RCU infrastructure make heavy use of batching in
+order to amortize their overhead over many uses of the corresponding APIs.
+
+There are no fewer than three RCU mechanisms in the Linux kernel; the
+diagram above shows the first one, which is by far the most commonly used.
+The rcu_dereference() and rcu_assign_pointer() primitives are used for
+all three mechanisms, but different defer and protect primitives are
+used as follows:
+
+       Defer                   Protect
+
+a.     synchronize_rcu()       rcu_read_lock() / rcu_read_unlock()
+       call_rcu()
+
+b.     call_rcu_bh()           rcu_read_lock_bh() / rcu_read_unlock_bh()
+
+c.     synchronize_sched()     preempt_disable() / preempt_enable()
+                               local_irq_save() / local_irq_restore()
+                               hardirq enter / hardirq exit
+                               NMI enter / NMI exit
+
+These three mechanisms are used as follows:
+
+a.     RCU applied to normal data structures.
+
+b.     RCU applied to networking data structures that may be subjected
+       to remote denial-of-service attacks.
+
+c.     RCU applied to scheduler and interrupt/NMI-handler tasks.
+
+Again, most uses will be of (a).  The (b) and (c) cases are important
+for specialized uses, but are relatively uncommon.
+
+
+3.  WHAT ARE SOME EXAMPLE USES OF CORE RCU API?
+
+This section shows a simple use of the core RCU API to protect a
+global pointer to a dynamically allocated structure.  More typical
+uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt.
+
+       struct foo {
+               int a;
+               char b;
+               long c;
+       };
+       DEFINE_SPINLOCK(foo_mutex);
+
+       struct foo *gbl_foo;
+
+       /*
+        * Create a new struct foo that is the same as the one currently
+        * pointed to by gbl_foo, except that field "a" is replaced
+        * with "new_a".  Points gbl_foo to the new structure, and
+        * frees up the old structure after a grace period.
+        *
+        * Uses rcu_assign_pointer() to ensure that concurrent readers
+        * see the initialized version of the new structure.
+        *
+        * Uses synchronize_rcu() to ensure that any readers that might
+        * have references to the old structure complete before freeing
+        * the old structure.
+        */
+       void foo_update_a(int new_a)
+       {
+               struct foo *new_fp;
+               struct foo *old_fp;
+
+               new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+               spin_lock(&foo_mutex);
+               old_fp = gbl_foo;
+               *new_fp = *old_fp;
+               new_fp->a = new_a;
+               rcu_assign_pointer(gbl_foo, new_fp);
+               spin_unlock(&foo_mutex);
+               synchronize_rcu();
+               kfree(old_fp);
+       }
+
+       /*
+        * Return the value of field "a" of the current gbl_foo
+        * structure.  Use rcu_read_lock() and rcu_read_unlock()
+        * to ensure that the structure does not get deleted out
+        * from under us, and use rcu_dereference() to ensure that
+        * we see the initialized version of the structure (important
+        * for DEC Alpha and for people reading the code).
+        */
+       int foo_get_a(void)
+       {
+               int retval;
+
+               rcu_read_lock();
+               retval = rcu_dereference(gbl_foo)->a;
+               rcu_read_unlock();
+               return retval;
+       }
+
+So, to sum up:
+
+o      Use rcu_read_lock() and rcu_read_unlock() to guard RCU
+       read-side critical sections.
+
+o      Within an RCU read-side critical section, use rcu_dereference()
+       to dereference RCU-protected pointers.
+
+o      Use some solid scheme (such as locks or semaphores) to
+       keep concurrent updates from interfering with each other.
+
+o      Use rcu_assign_pointer() to update an RCU-protected pointer.
+       This primitive protects concurrent readers from the updater,
+       -not- concurrent updates from each other!  You therefore still
+       need to use locking (or something similar) to keep concurrent
+       rcu_assign_pointer() primitives from interfering with each other.
+
+o      Use synchronize_rcu() -after- removing a data element from an
+       RCU-protected data structure, but -before- reclaiming/freeing
+       the data element, in order to wait for the completion of all
+       RCU read-side critical sections that might be referencing that
+       data item.
+
+See checklist.txt for additional rules to follow when using RCU.
+
+
+4.  WHAT IF MY UPDATING THREAD CANNOT BLOCK?
+
+In the example above, foo_update_a() blocks until a grace period elapses.
+This is quite simple, but in some cases one cannot afford to wait so
+long -- there might be other high-priority work to be done.
+
+In such cases, one uses call_rcu() rather than synchronize_rcu().
+The call_rcu() API is as follows:
+
+       void call_rcu(struct rcu_head * head,
+                     void (*func)(struct rcu_head *head));
+
+This function invokes func(head) after a grace period has elapsed.
+This invocation might happen from either softirq or process context,
+so the function is not permitted to block.  The foo struct needs to
+have an rcu_head structure added, perhaps as follows:
+
+       struct foo {
+               int a;
+               char b;
+               long c;
+               struct rcu_head rcu;
+       };
+
+The foo_update_a() function might then be written as follows:
+
+       /*
+        * Create a new struct foo that is the same as the one currently
+        * pointed to by gbl_foo, except that field "a" is replaced
+        * with "new_a".  Points gbl_foo to the new structure, and
+        * frees up the old structure after a grace period.
+        *
+        * Uses rcu_assign_pointer() to ensure that concurrent readers
+        * see the initialized version of the new structure.
+        *
+        * Uses call_rcu() to ensure that any readers that might have
+        * references to the old structure complete before freeing the
+        * old structure.
+        */
+       void foo_update_a(int new_a)
+       {
+               struct foo *new_fp;
+               struct foo *old_fp;
+
+               new_fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+               spin_lock(&foo_mutex);
+               old_fp = gbl_foo;
+               *new_fp = *old_fp;
+               new_fp->a = new_a;
+               rcu_assign_pointer(gbl_foo, new_fp);
+               spin_unlock(&foo_mutex);
+               call_rcu(&old_fp->rcu, foo_reclaim);
+       }
+
+The foo_reclaim() function might appear as follows:
+
+       void foo_reclaim(struct rcu_head *rp)
+       {
+               struct foo *fp = container_of(rp, struct foo, rcu);
+
+               kfree(fp);
+       }
+
+The container_of() primitive is a macro that, given a pointer into a
+struct, the type of the struct, and the pointed-to field within the
+struct, returns a pointer to the beginning of the struct.
+
+The use of call_rcu() permits the caller of foo_update_a() to
+immediately regain control, without needing to worry further about the
+old version of the newly updated element.  It also clearly shows the
+RCU distinction between updater, namely foo_update_a(), and reclaimer,
+namely foo_reclaim().
+
+The summary of advice is the same as for the previous section, except
+that we are now using call_rcu() rather than synchronize_rcu():
+
+o      Use call_rcu() -after- removing a data element from an
+       RCU-protected data structure in order to register a callback
+       function that will be invoked after the completion of all RCU
+       read-side critical sections that might be referencing that
+       data item.
+
+Again, see checklist.txt for additional rules governing the use of RCU.
+
+
+5.  WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU?
+
+One of the nice things about RCU is that it has extremely simple "toy"
+implementations that are a good first step towards understanding the
+production-quality implementations in the Linux kernel.  This section
+presents two such "toy" implementations of RCU, one that is implemented
+in terms of familiar locking primitives, and another that more closely
+resembles "classic" RCU.  Both are way too simple for real-world use,
+lacking both functionality and performance.  However, they are useful
+in getting a feel for how RCU works.  See kernel/rcupdate.c for a
+production-quality implementation, and see:
+
+       http://www.rdrop.com/users/paulmck/RCU
+
+for papers describing the Linux kernel RCU implementation.  The OLS'01
+and OLS'02 papers are a good introduction, and the dissertation provides
+more details on the current implementation.
+
+
+5A.  "TOY" IMPLEMENTATION #1: LOCKING
+
+This section presents a "toy" RCU implementation that is based on
+familiar locking primitives.  Its overhead makes it a non-starter for
+real-life use, as does its lack of scalability.  It is also unsuitable
+for realtime use, since it allows scheduling latency to "bleed" from
+one read-side critical section to another.
+
+However, it is probably the easiest implementation to relate to, so is
+a good starting point.
+
+It is extremely simple:
+
+       static DEFINE_RWLOCK(rcu_gp_mutex);
+
+       void rcu_read_lock(void)
+       {
+               read_lock(&rcu_gp_mutex);
+       }
+
+       void rcu_read_unlock(void)
+       {
+               read_unlock(&rcu_gp_mutex);
+       }
+
+       void synchronize_rcu(void)
+       {
+               write_lock(&rcu_gp_mutex);
+               write_unlock(&rcu_gp_mutex);
+       }
+
+[You can ignore rcu_assign_pointer() and rcu_dereference() without
+missing much.  But here they are anyway.  And whatever you do, don't
+forget about them when submitting patches making use of RCU!]
+
+       #define rcu_assign_pointer(p, v)        ({ \
+                                                       smp_wmb(); \
+                                                       (p) = (v); \
+                                               })
+
+       #define rcu_dereference(p)     ({ \
+                                       typeof(p) _________p1 = p; \
+                                       smp_read_barrier_depends(); \
+                                       (_________p1); \
+                                       })
+
+
+The rcu_read_lock() and rcu_read_unlock() primitive read-acquire
+and release a global reader-writer lock.  The synchronize_rcu()
+primitive write-acquires this same lock, then immediately releases
+it.  This means that once synchronize_rcu() exits, all RCU read-side
+critical sections that were in progress before synchonize_rcu() was
+called are guaranteed to have completed -- there is no way that
+synchronize_rcu() would have been able to write-acquire the lock
+otherwise.
+
+It is possible to nest rcu_read_lock(), since reader-writer locks may
+be recursively acquired.  Note also that rcu_read_lock() is immune
+from deadlock (an important property of RCU).  The reason for this is
+that the only thing that can block rcu_read_lock() is a synchronize_rcu().
+But synchronize_rcu() does not acquire any locks while holding rcu_gp_mutex,
+so there can be no deadlock cycle.
+
+Quick Quiz #1: Why is this argument naive?  How could a deadlock
+               occur when using this algorithm in a real-world Linux
+               kernel?  How could this deadlock be avoided?
+
+
+5B.  "TOY" EXAMPLE #2: CLASSIC RCU
+
+This section presents a "toy" RCU implementation that is based on
+"classic RCU".  It is also short on performance (but only for updates) and
+on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT
+kernels.  The definitions of rcu_dereference() and rcu_assign_pointer()
+are the same as those shown in the preceding section, so they are omitted.
+
+       void rcu_read_lock(void) { }
+
+       void rcu_read_unlock(void) { }
+
+       void synchronize_rcu(void)
+       {
+               int cpu;
+
+               for_each_cpu(cpu)
+                       run_on(cpu);
+       }
+
+Note that rcu_read_lock() and rcu_read_unlock() do absolutely nothing.
+This is the great strength of classic RCU in a non-preemptive kernel:
+read-side overhead is precisely zero, at least on non-Alpha CPUs.
+And there is absolutely no way that rcu_read_lock() can possibly
+participate in a deadlock cycle!
+
+The implementation of synchronize_rcu() simply schedules itself on each
+CPU in turn.  The run_on() primitive can be implemented straightforwardly
+in terms of the sched_setaffinity() primitive.  Of course, a somewhat less
+"toy" implementation would restore the affinity upon completion rather
+than just leaving all tasks running on the last CPU, but when I said
+"toy", I meant -toy-!
+
+So how the heck is this supposed to work???
+
+Remember that it is illegal to block while in an RCU read-side critical
+section.  Therefore, if a given CPU executes a context switch, we know
+that it must have completed all preceding RCU read-side critical sections.
+Once -all- CPUs have executed a context switch, then -all- preceding
+RCU read-side critical sections will have completed.
+
+So, suppose that we remove a data item from its structure and then invoke
+synchronize_rcu().  Once synchronize_rcu() returns, we are guaranteed
+that there are no RCU read-side critical sections holding a reference
+to that data item, so we can safely reclaim it.
+
+Quick Quiz #2: Give an example where Classic RCU's read-side
+               overhead is -negative-.
+
+Quick Quiz #3:  If it is illegal to block in an RCU read-side
+               critical section, what the heck do you do in
+               PREEMPT_RT, where normal spinlocks can block???
+
+
+6.  ANALOGY WITH READER-WRITER LOCKING
+
+Although RCU can be used in many different ways, a very common use of
+RCU is analogous to reader-writer locking.  The following unified
+diff shows how closely related RCU and reader-writer locking can be.
+
+       @@ -13,15 +14,15 @@
+               struct list_head *lp;
+               struct el *p;
+
+       -       read_lock();
+       -       list_for_each_entry(p, head, lp) {
+       +       rcu_read_lock();
+       +       list_for_each_entry_rcu(p, head, lp) {
+                       if (p->key == key) {
+                               *result = p->data;
+       -                       read_unlock();
+       +                       rcu_read_unlock();
+                               return 1;
+                       }
+               }
+       -       read_unlock();
+       +       rcu_read_unlock();
+               return 0;
+        }
+
+       @@ -29,15 +30,16 @@
+        {
+               struct el *p;
+
+       -       write_lock(&listmutex);
+       +       spin_lock(&listmutex);
+               list_for_each_entry(p, head, lp) {
+                       if (p->key == key) {
+                               list_del(&p->list);
+       -                       write_unlock(&listmutex);
+       +                       spin_unlock(&listmutex);
+       +                       synchronize_rcu();
+                               kfree(p);
+                               return 1;
+                       }
+               }
+       -       write_unlock(&listmutex);
+       +       spin_unlock(&listmutex);
+               return 0;
+        }
+
+Or, for those who prefer a side-by-side listing:
+
+ 1 struct el {                          1 struct el {
+ 2   struct list_head list;             2   struct list_head list;
+ 3   long key;                          3   long key;
+ 4   spinlock_t mutex;                  4   spinlock_t mutex;
+ 5   int data;                          5   int data;
+ 6   /* Other data fields */            6   /* Other data fields */
+ 7 };                                   7 };
+ 8 spinlock_t listmutex;                8 spinlock_t listmutex;
+ 9 struct el head;                      9 struct el head;
+
+ 1 int search(long key, int *result)    1 int search(long key, int *result)
+ 2 {                                    2 {
+ 3   struct list_head *lp;              3   struct list_head *lp;
+ 4   struct el *p;                      4   struct el *p;
+ 5                                      5
+ 6   read_lock();                       6   rcu_read_lock();
+ 7   list_for_each_entry(p, head, lp) { 7   list_for_each_entry_rcu(p, head, lp) {
+ 8     if (p->key == key) {             8     if (p->key == key) {
+ 9       *result = p->data;             9       *result = p->data;
+10       read_unlock();                10       rcu_read_unlock();
+11       return 1;                     11       return 1;
+12     }                               12     }
+13   }                                 13   }
+14   read_unlock();                    14   rcu_read_unlock();
+15   return 0;                         15   return 0;
+16 }                                   16 }
+
+ 1 int delete(long key)                 1 int delete(long key)
+ 2 {                                    2 {
+ 3   struct el *p;                      3   struct el *p;
+ 4                                      4
+ 5   write_lock(&listmutex);            5   spin_lock(&listmutex);
+ 6   list_for_each_entry(p, head, lp) { 6   list_for_each_entry(p, head, lp) {
+ 7     if (p->key == key) {             7     if (p->key == key) {
+ 8       list_del(&p->list);            8       list_del(&p->list);
+ 9       write_unlock(&listmutex);      9       spin_unlock(&listmutex);
+                                       10       synchronize_rcu();
+10       kfree(p);                     11       kfree(p);
+11       return 1;                     12       return 1;
+12     }                               13     }
+13   }                                 14   }
+14   write_unlock(&listmutex);         15   spin_unlock(&listmutex);
+15   return 0;                         16   return 0;
+16 }                                   17 }
+
+Either way, the differences are quite small.  Read-side locking moves
+to rcu_read_lock() and rcu_read_unlock, update-side locking moves from
+from a reader-writer lock to a simple spinlock, and a synchronize_rcu()
+precedes the kfree().
+
+However, there is one potential catch: the read-side and update-side
+critical sections can now run concurrently.  In many cases, this will
+not be a problem, but it is necessary to check carefully regardless.
+For example, if multiple independent list updates must be seen as
+a single atomic update, converting to RCU will require special care.
+
+Also, the presence of synchronize_rcu() means that the RCU version of
+delete() can now block.  If this is a problem, there is a callback-based
+mechanism that never blocks, namely call_rcu(), that can be used in
+place of synchronize_rcu().
+
+
+7.  FULL LIST OF RCU APIs
+
+The RCU APIs are documented in docbook-format header comments in the
+Linux-kernel source code, but it helps to have a full list of the
+APIs, since there does not appear to be a way to categorize them
+in docbook.  Here is the list, by category.
+
+Markers for RCU read-side critical sections:
+
+       rcu_read_lock
+       rcu_read_unlock
+       rcu_read_lock_bh
+       rcu_read_unlock_bh
+
+RCU pointer/list traversal:
+
+       rcu_dereference
+       list_for_each_rcu               (to be deprecated in favor of
+                                        list_for_each_entry_rcu)
+       list_for_each_safe_rcu          (deprecated, not used)
+       list_for_each_entry_rcu
+       list_for_each_continue_rcu      (to be deprecated in favor of new
+                                        list_for_each_entry_continue_rcu)
+       hlist_for_each_rcu              (to be deprecated in favor of
+                                        hlist_for_each_entry_rcu)
+       hlist_for_each_entry_rcu
+
+RCU pointer update:
+
+       rcu_assign_pointer
+       list_add_rcu
+       list_add_tail_rcu
+       list_del_rcu
+       list_replace_rcu
+       hlist_del_rcu
+       hlist_add_head_rcu
+
+RCU grace period:
+
+       synchronize_kernel (deprecated)
+       synchronize_net
+       synchronize_sched
+       synchronize_rcu
+       call_rcu
+       call_rcu_bh
+
+See the comment headers in the source code (or the docbook generated
+from them) for more information.
+
+
+8.  ANSWERS TO QUICK QUIZZES
+
+Quick Quiz #1: Why is this argument naive?  How could a deadlock
+               occur when using this algorithm in a real-world Linux
+               kernel?  [Referring to the lock-based "toy" RCU
+               algorithm.]
+
+Answer:                Consider the following sequence of events:
+
+               1.      CPU 0 acquires some unrelated lock, call it
+                       "problematic_lock".
+
+               2.      CPU 1 enters synchronize_rcu(), write-acquiring
+                       rcu_gp_mutex.
+
+               3.      CPU 0 enters rcu_read_lock(), but must wait
+                       because CPU 1 holds rcu_gp_mutex.
+
+               4.      CPU 1 is interrupted, and the irq handler
+                       attempts to acquire problematic_lock.
+
+               The system is now deadlocked.
+
+               One way to avoid this deadlock is to use an approach like
+               that of CONFIG_PREEMPT_RT, where all normal spinlocks
+               become blocking locks, and all irq handlers execute in
+               the context of special tasks.  In this case, in step 4
+               above, the irq handler would block, allowing CPU 1 to
+               release rcu_gp_mutex, avoiding the deadlock.
+
+               Even in the absence of deadlock, this RCU implementation
+               allows latency to "bleed" from readers to other
+               readers through synchronize_rcu().  To see this,
+               consider task A in an RCU read-side critical section
+               (thus read-holding rcu_gp_mutex), task B blocked
+               attempting to write-acquire rcu_gp_mutex, and
+               task C blocked in rcu_read_lock() attempting to
+               read_acquire rcu_gp_mutex.  Task A's RCU read-side
+               latency is holding up task C, albeit indirectly via
+               task B.
+
+               Realtime RCU implementations therefore use a counter-based
+               approach where tasks in RCU read-side critical sections
+               cannot be blocked by tasks executing synchronize_rcu().
+
+Quick Quiz #2: Give an example where Classic RCU's read-side
+               overhead is -negative-.
+
+Answer:                Imagine a single-CPU system with a non-CONFIG_PREEMPT
+               kernel where a routing table is used by process-context
+               code, but can be updated by irq-context code (for example,
+               by an "ICMP REDIRECT" packet).  The usual way of handling
+               this would be to have the process-context code disable
+               interrupts while searching the routing table.  Use of
+               RCU allows such interrupt-disabling to be dispensed with.
+               Thus, without RCU, you pay the cost of disabling interrupts,
+               and with RCU you don't.
+
+               One can argue that the overhead of RCU in this
+               case is negative with respect to the single-CPU
+               interrupt-disabling approach.  Others might argue that
+               the overhead of RCU is merely zero, and that replacing
+               the positive overhead of the interrupt-disabling scheme
+               with the zero-overhead RCU scheme does not constitute
+               negative overhead.
+
+               In real life, of course, things are more complex.  But
+               even the theoretical possibility of negative overhead for
+               a synchronization primitive is a bit unexpected.  ;-)
+
+Quick Quiz #3:  If it is illegal to block in an RCU read-side
+               critical section, what the heck do you do in
+               PREEMPT_RT, where normal spinlocks can block???
+
+Answer:                Just as PREEMPT_RT permits preemption of spinlock
+               critical sections, it permits preemption of RCU
+               read-side critical sections.  It also permits
+               spinlocks blocking while in RCU read-side critical
+               sections.
+
+               Why the apparent inconsistency?  Because it is it
+               possible to use priority boosting to keep the RCU
+               grace periods short if need be (for example, if running
+               short of memory).  In contrast, if blocking waiting
+               for (say) network reception, there is no way to know
+               what should be boosted.  Especially given that the
+               process we need to boost might well be a human being
+               who just went out for a pizza or something.  And although
+               a computer-operated cattle prod might arouse serious
+               interest, it might also provoke serious objections.
+               Besides, how does the computer know what pizza parlor
+               the human being went to???
+
+
+ACKNOWLEDGEMENTS
+
+My thanks to the people who helped make this human-readable, including
+Jon Walpole, Josh Triplett, Serge Hallyn, and Suzanne Wood.
+
+
+For more information, see http://www.rdrop.com/users/paulmck/RCU.
diff --git a/Documentation/applying-patches.txt b/Documentation/applying-patches.txt
new file mode 100644 (file)
index 0000000..681e426
--- /dev/null
@@ -0,0 +1,439 @@
+
+       Applying Patches To The Linux Kernel
+       ------------------------------------
+
+       (Written by Jesper Juhl, August 2005)
+
+
+
+A frequently asked question on the Linux Kernel Mailing List is how to apply
+a patch to the kernel or, more specifically, what base kernel a patch for
+one of the many trees/branches should be applied to. Hopefully this document
+will explain this to you.
+
+In addition to explaining how to apply and revert patches, a brief
+description of the different kernel trees (and examples of how to apply
+their specific patches) is also provided.
+
+
+What is a patch?
+---
+ A patch is a small text document containing a delta of changes between two
+different versions of a source tree. Patches are created with the `diff'
+program.
+To correctly apply a patch you need to know what base it was generated from
+and what new version the patch will change the source tree into. These
+should both be present in the patch file metadata or be possible to deduce
+from the filename.
+
+
+How do I apply or revert a patch?
+---
+ You apply a patch with the `patch' program. The patch program reads a diff
+(or patch) file and makes the changes to the source tree described in it.
+
+Patches for the Linux kernel are generated relative to the parent directory
+holding the kernel source dir.
+
+This means that paths to files inside the patch file contain the name of the
+kernel source directories it was generated against (or some other directory
+names like "a/" and "b/").
+Since this is unlikely to match the name of the kernel source dir on your
+local machine (but is often useful info to see what version an otherwise
+unlabeled patch was generated against) you should change into your kernel
+source directory and then strip the first element of the path from filenames
+in the patch file when applying it (the -p1 argument to `patch' does this).
+
+To revert a previously applied patch, use the -R argument to patch.
+So, if you applied a patch like this:
+       patch -p1 < ../patch-x.y.z
+
+You can revert (undo) it like this:
+       patch -R -p1 < ../patch-x.y.z
+
+
+How do I feed a patch/diff file to `patch'?
+---
+ This (as usual with Linux and other UNIX like operating systems) can be
+done in several different ways.
+In all the examples below I feed the file (in uncompressed form) to patch
+via stdin using the following syntax:
+       patch -p1 < path/to/patch-x.y.z
+
+If you just want to be able to follow the examples below and don't want to
+know of more than one way to use patch, then you can stop reading this
+section here.
+
+Patch can also get the name of the file to use via the -i argument, like
+this:
+       patch -p1 -i path/to/patch-x.y.z
+
+If your patch file is compressed with gzip or bzip2 and you don't want to
+uncompress it before applying it, then you can feed it to patch like this
+instead:
+       zcat path/to/patch-x.y.z.gz | patch -p1
+       bzcat path/to/patch-x.y.z.bz2 | patch -p1
+
+If you wish to uncompress the patch file by hand first before applying it
+(what I assume you've done in the examples below), then you simply run
+gunzip or bunzip2 on the file - like this:
+       gunzip patch-x.y.z.gz
+       bunzip2 patch-x.y.z.bz2
+
+Which will leave you with a plain text patch-x.y.z file that you can feed to
+patch via stdin or the -i argument, as you prefer.
+
+A few other nice arguments for patch are -s which causes patch to be silent
+except for errors which is nice to prevent errors from scrolling out of the
+screen too fast, and --dry-run which causes patch to just print a listing of
+what would happen, but doesn't actually make any changes. Finally --verbose
+tells patch to print more information about the work being done.
+
+
+Common errors when patching
+---
+ When patch applies a patch file it attempts to verify the sanity of the
+file in different ways.
+Checking that the file looks like a valid patch file, checking the code
+around the bits being modified matches the context provided in the patch are
+just two of the basic sanity checks patch does.
+
+If patch encounters something that doesn't look quite right it has two
+options. It can either refuse to apply the changes and abort or it can try
+to find a way to make the patch apply with a few minor changes.
+
+One example of something that's not 'quite right' that patch will attempt to
+fix up is if all the context matches, the lines being changed match, but the
+line numbers are different. This can happen, for example, if the patch makes
+a change in the middle of the file but for some reasons a few lines have
+been added or removed near the beginning of the file. In that case
+everything looks good it has just moved up or down a bit, and patch will
+usually adjust the line numbers and apply the patch.
+
+Whenever patch applies a patch that it had to modify a bit to make it fit
+it'll tell you about it by saying the patch applied with 'fuzz'.
+You should be wary of such changes since even though patch probably got it
+right it doesn't /always/ get it right, and the result will sometimes be
+wrong.
+
+When patch encounters a change that it can't fix up with fuzz it rejects it
+outright and leaves a file with a .rej extension (a reject file). You can
+read this file to see exactely what change couldn't be applied, so you can
+go fix it up by hand if you wish.
+
+If you don't have any third party patches applied to your kernel source, but
+only patches from kernel.org and you apply the patches in the correct order,
+and have made no modifications yourself to the source files, then you should
+never see a fuzz or reject message from patch. If you do see such messages
+anyway, then there's a high risk that either your local source tree or the
+patch file is corrupted in some way. In that case you should probably try
+redownloading the patch and if things are still not OK then you'd be advised
+to start with a fresh tree downloaded in full from kernel.org.
+
+Let's look a bit more at some of the messages patch can produce.
+
+If patch stops and presents a "File to patch:" prompt, then patch could not
+find a file to be patched. Most likely you forgot to specify -p1 or you are
+in the wrong directory. Less often, you'll find patches that need to be
+applied with -p0 instead of -p1 (reading the patch file should reveal if
+this is the case - if so, then this is an error by the person who created
+the patch but is not fatal).
+
+If you get "Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines)." or a
+message similar to that, then it means that patch had to adjust the location
+of the change (in this example it needed to move 7 lines from where it
+expected to make the change to make it fit).
+The resulting file may or may not be OK, depending on the reason the file
+was different than expected.
+This often happens if you try to apply a patch that was generated against a
+different kernel version than the one you are trying to patch.
+
+If you get a message like "Hunk #3 FAILED at 2387.", then it means that the
+patch could not be applied correctly and the patch program was unable to
+fuzz its way through. This will generate a .rej file with the change that
+caused the patch to fail and also a .orig file showing you the original
+content that couldn't be changed.
+
+If you get "Reversed (or previously applied) patch detected!  Assume -R? [n]"
+then patch detected that the change contained in the patch seems to have
+already been made.
+If you actually did apply this patch previously and you just re-applied it
+in error, then just say [n]o and abort this patch. If you applied this patch
+previously and actually intended to revert it, but forgot to specify -R,
+then you can say [y]es here to make patch revert it for you.
+This can also happen if the creator of the patch reversed the source and
+destination directories when creating the patch, and in that case reverting
+the patch will in fact apply it.
+
+A message similar to "patch: **** unexpected end of file in patch" or "patch
+unexpectedly ends in middle of line" means that patch could make no sense of
+the file you fed to it. Either your download is broken or you tried to feed
+patch a compressed patch file without uncompressing it first.
+
+As I already mentioned above, these errors should never happen if you apply
+a patch from kernel.org to the correct version of an unmodified source tree.
+So if you get these errors with kernel.org patches then you should probably
+assume that either your patch file or your tree is broken and I'd advice you
+to start over with a fresh download of a full kernel tree and the patch you
+wish to apply.
+
+
+Are there any alternatives to `patch'?
+---
+ Yes there are alternatives. You can use the `interdiff' program
+(http://cyberelk.net/tim/patchutils/) to generate a patch representing the
+differences between two patches and then apply the result.
+This will let you move from something like 2.6.12.2 to 2.6.12.3 in a single
+step. The -z flag to interdiff will even let you feed it patches in gzip or
+bzip2 compressed form directly without the use of zcat or bzcat or manual
+decompression.
+
+Here's how you'd go from 2.6.12.2 to 2.6.12.3 in a single step:
+       interdiff -z ../patch-2.6.12.2.bz2 ../patch-2.6.12.3.gz | patch -p1
+
+Although interdiff may save you a step or two you are generally advised to
+do the additional steps since interdiff can get things wrong in some cases.
+
+ Another alternative is `ketchup', which is a python script for automatic
+downloading and applying of patches (http://www.selenic.com/ketchup/).
+
+Other nice tools are diffstat which shows a summary of changes made by a
+patch, lsdiff which displays a short listing of affected files in a patch
+file, along with (optionally) the line numbers of the start of each patch
+and grepdiff which displays a list of the files modified by a patch where
+the patch contains a given regular expression.
+
+
+Where can I download the patches?
+---
+ The patches are available at http://kernel.org/
+Most recent patches are linked from the front page, but they also have
+specific homes.
+
+The 2.6.x.y (-stable) and 2.6.x patches live at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
+
+The -rc patches live at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/testing/
+
+The -git patches live at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/snapshots/
+
+The -mm kernels live at
+ ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/
+
+In place of ftp.kernel.org you can use ftp.cc.kernel.org, where cc is a
+country code. This way you'll be downloading from a mirror site that's most
+likely geographically closer to you, resulting in faster downloads for you,
+less bandwidth used globally and less load on the main kernel.org servers -
+these are good things, do use mirrors when possible.
+
+
+The 2.6.x kernels
+---
+ These are the base stable releases released by Linus. The highest numbered
+release is the most recent.
+
+If regressions or other serious flaws are found then a -stable fix patch
+will be released (see below) on top of this base. Once a new 2.6.x base
+kernel is released, a patch is made available that is a delta between the
+previous 2.6.x kernel and the new one.
+
+To apply a patch moving from 2.6.11 to 2.6.12 you'd do the following (note
+that such patches do *NOT* apply on top of 2.6.x.y kernels but on top of the
+base 2.6.x kernel - if you need to move from 2.6.x.y to 2.6.x+1 you need to
+first revert the 2.6.x.y patch).
+
+Here are some examples:
+
+# moving from 2.6.11 to 2.6.12
+$ cd ~/linux-2.6.11                    # change to kernel source dir
+$ patch -p1 < ../patch-2.6.12          # apply the 2.6.12 patch
+$ cd ..
+$ mv linux-2.6.11 linux-2.6.12         # rename source dir
+
+# moving from 2.6.11.1 to 2.6.12
+$ cd ~/linux-2.6.11.1                  # change to kernel source dir
+$ patch -p1 -R < ../patch-2.6.11.1     # revert the 2.6.11.1 patch
+                                       # source dir is now 2.6.11
+$ patch -p1 < ../patch-2.6.12          # apply new 2.6.12 patch
+$ cd ..
+$ mv linux-2.6.11.1 inux-2.6.12                # rename source dir
+
+
+The 2.6.x.y kernels
+---
+ Kernels with 4 digit versions are -stable kernels. They contain small(ish)
+critical fixes for security problems or significant regressions discovered
+in a given 2.6.x kernel.
+
+This is the recommended branch for users who want the most recent stable
+kernel and are not interested in helping test development/experimental
+versions.
+
+If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is
+the current stable kernel.
+
+These patches are not incremental, meaning that for example the 2.6.12.3
+patch does not apply on top of the 2.6.12.2 kernel source, but rather on top
+of the base 2.6.12 kernel source.
+So, in order to apply the 2.6.12.3 patch to your existing 2.6.12.2 kernel
+source you have to first back out the 2.6.12.2 patch (so you are left with a
+base 2.6.12 kernel source) and then apply the new 2.6.12.3 patch.
+
+Here's a small example:
+
+$ cd ~/linux-2.6.12.2                  # change into the kernel source dir
+$ patch -p1 -R < ../patch-2.6.12.2     # revert the 2.6.12.2 patch
+$ patch -p1 < ../patch-2.6.12.3                # apply the new 2.6.12.3 patch
+$ cd ..
+$ mv linux-2.6.12.2 linux-2.6.12.3     # rename the kernel source dir
+
+
+The -rc kernels
+---
+ These are release-candidate kernels. These are development kernels released
+by Linus whenever he deems the current git (the kernel's source management
+tool) tree to be in a reasonably sane state adequate for testing.
+
+These kernels are not stable and you should expect occasional breakage if
+you intend to run them. This is however the most stable of the main
+development branches and is also what will eventually turn into the next
+stable kernel, so it is important that it be tested by as many people as
+possible.
+
+This is a good branch to run for people who want to help out testing
+development kernels but do not want to run some of the really experimental
+stuff (such people should see the sections about -git and -mm kernels below).
+
+The -rc patches are not incremental, they apply to a base 2.6.x kernel, just
+like the 2.6.x.y patches described above. The kernel version before the -rcN
+suffix denotes the version of the kernel that this -rc kernel will eventually
+turn into.
+So, 2.6.13-rc5 means that this is the fifth release candidate for the 2.6.13
+kernel and the patch should be applied on top of the 2.6.12 kernel source.
+
+Here are 3 examples of how to apply these patches:
+
+# first an example of moving from 2.6.12 to 2.6.13-rc3
+$ cd ~/linux-2.6.12                    # change into the 2.6.12 source dir
+$ patch -p1 < ../patch-2.6.13-rc3      # apply the 2.6.13-rc3 patch
+$ cd ..
+$ mv linux-2.6.12 linux-2.6.13-rc3     # rename the source dir
+
+# now let's move from 2.6.13-rc3 to 2.6.13-rc5
+$ cd ~/linux-2.6.13-rc3                        # change into the 2.6.13-rc3 dir
+$ patch -p1 -R < ../patch-2.6.13-rc3   # revert the 2.6.13-rc3 patch
+$ patch -p1 < ../patch-2.6.13-rc5      # apply the new 2.6.13-rc5 patch
+$ cd ..
+$ mv linux-2.6.13-rc3 linux-2.6.13-rc5 # rename the source dir
+
+# finally let's try and move from 2.6.12.3 to 2.6.13-rc5
+$ cd ~/linux-2.6.12.3                  # change to the kernel source dir
+$ patch -p1 -R < ../patch-2.6.12.3     # revert the 2.6.12.3 patch
+$ patch -p1 < ../patch-2.6.13-rc5      # apply new 2.6.13-rc5 patch
+$ cd ..
+$ mv linux-2.6.12.3 linux-2.6.13-rc5   # rename the kernel source dir
+
+
+The -git kernels
+---
+ These are daily snapshots of Linus' kernel tree (managed in a git
+repository, hence the name).
+
+These patches are usually released daily and represent the current state of
+Linus' tree. They are more experimental than -rc kernels since they are
+generated automatically without even a cursory glance to see if they are
+sane.
+
+-git patches are not incremental and apply either to a base 2.6.x kernel or
+a base 2.6.x-rc kernel - you can see which from their name.
+A patch named 2.6.12-git1 applies to the 2.6.12 kernel source and a patch
+named 2.6.13-rc3-git2 applies to the source of the 2.6.13-rc3 kernel.
+
+Here are some examples of how to apply these patches:
+
+# moving from 2.6.12 to 2.6.12-git1
+$ cd ~/linux-2.6.12                    # change to the kernel source dir
+$ patch -p1 < ../patch-2.6.12-git1     # apply the 2.6.12-git1 patch
+$ cd ..
+$ mv linux-2.6.12 linux-2.6.12-git1    # rename the kernel source dir
+
+# moving from 2.6.12-git1 to 2.6.13-rc2-git3
+$ cd ~/linux-2.6.12-git1               # change to the kernel source dir
+$ patch -p1 -R < ../patch-2.6.12-git1  # revert the 2.6.12-git1 patch
+                                       # we now have a 2.6.12 kernel
+$ patch -p1 < ../patch-2.6.13-rc2      # apply the 2.6.13-rc2 patch
+                                       # the kernel is now 2.6.13-rc2
+$ patch -p1 < ../patch-2.6.13-rc2-git3 # apply the 2.6.13-rc2-git3 patch
+                                       # the kernel is now 2.6.13-rc2-git3
+$ cd ..
+$ mv linux-2.6.12-git1 linux-2.6.13-rc2-git3   # rename source dir
+
+
+The -mm kernels
+---
+ These are experimental kernels released by Andrew Morton.
+
+The -mm tree serves as a sort of proving ground for new features and other
+experimental patches.
+Once a patch has proved its worth in -mm for a while Andrew pushes it on to
+Linus for inclusion in mainline.
+
+Although it's encouraged that patches flow to Linus via the -mm tree, this
+is not always enforced.
+Subsystem maintainers (or individuals) sometimes push their patches directly
+to Linus, even though (or after) they have been merged and tested in -mm (or
+sometimes even without prior testing in -mm).
+
+You should generally strive to get your patches into mainline via -mm to
+ensure maximum testing.
+
+This branch is in constant flux and contains many experimental features, a
+lot of debugging patches not appropriate for mainline etc and is the most
+experimental of the branches described in this document.
+
+These kernels are not appropriate for use on systems that are supposed to be
+stable and they are more risky to run than any of the other branches (make
+sure you have up-to-date backups - that goes for any experimental kernel but
+even more so for -mm kernels).
+
+These kernels in addition to all the other experimental patches they contain
+usually also contain any changes in the mainline -git kernels available at
+the time of release.
+
+Testing of -mm kernels is greatly appreciated since the whole point of the
+tree is to weed out regressions, crashes, data corruption bugs, build
+breakage (and any other bug in general) before changes are merged into the
+more stable mainline Linus tree.
+But testers of -mm should be aware that breakage in this tree is more common
+than in any other tree.
+
+The -mm kernels are not released on a fixed schedule, but usually a few -mm
+kernels are released in between each -rc kernel (1 to 3 is common).
+The -mm kernels apply to either a base 2.6.x kernel (when no -rc kernels
+have been released yet) or to a Linus -rc kernel.
+
+Here are some examples of applying the -mm patches:
+
+# moving from 2.6.12 to 2.6.12-mm1
+$ cd ~/linux-2.6.12                    # change to the 2.6.12 source dir
+$ patch -p1 < ../2.6.12-mm1            # apply the 2.6.12-mm1 patch
+$ cd ..
+$ mv linux-2.6.12 linux-2.6.12-mm1     # rename the source appropriately
+
+# moving from 2.6.12-mm1 to 2.6.13-rc3-mm3
+$ cd ~/linux-2.6.12-mm1
+$ patch -p1 -R < ../2.6.12-mm1         # revert the 2.6.12-mm1 patch
+                                       # we now have a 2.6.12 source
+$ patch -p1 < ../patch-2.6.13-rc3      # apply the 2.6.13-rc3 patch
+                                       # we now have a 2.6.13-rc3 source
+$ patch -p1 < ../2.6.13-rc3-mm3                # apply the 2.6.13-rc3-mm3 patch
+$ cd ..
+$ mv linux-2.6.12-mm1 linux-2.6.13-rc3-mm3     # rename the source dir
+
+
+This concludes this list of explanations of the various kernel trees and I
+hope you are now crystal clear on how to apply the various patches and help
+testing the kernel.
+
index e2d1e760b4ba3bd382d2034286c429fe4e6979fe..6a82948ff4bd59adb26b08e305339b4452f79edc 100644 (file)
@@ -36,7 +36,7 @@ cpufreq stats provides following statistics (explained in detail below).
 
 All the statistics will be from the time the stats driver has been inserted 
 to the time when a read of a particular statistic is done. Obviously, stats 
-driver will not have any information about the the frequcny transitions before
+driver will not have any information about the frequency transitions before
 the stats driver insertion.
 
 --------------------------------------------------------------------------------
index 47f4114fbf545459efbdad232392d93357eb6968..d17b7d2dd771e6c0eeeda4b93c372840209f014d 100644 (file)
@@ -277,7 +277,7 @@ rewritten to the 'tasks' file of its cpuset.  This is done to avoid
 impacting the scheduler code in the kernel with a check for changes
 in a tasks processor placement.
 
-There is an exception to the above.  If hotplug funtionality is used
+There is an exception to the above.  If hotplug functionality is used
 to remove all the CPUs that are currently assigned to a cpuset,
 then the kernel will automatically update the cpus_allowed of all
 tasks attached to CPUs in that cpuset to allow all CPUs.  When memory
index 166474c2ee0bdc23e34b0892ded4241626abd1cd..16e9e63507551989d726998d1ac769703f4325f2 100644 (file)
@@ -1,4 +1,4 @@
-Below is the orginal README file from the descore.shar package.
+Below is the original README file from the descore.shar package.
 ------------------------------------------------------------------------------
 
 des - fast & portable DES encryption & decryption.
index 4b8c326c6aac91fcd0d04db82b12114850376c52..cb63b7a93c82f02e47c79076bbf2723f0bec77d2 100644 (file)
@@ -1,55 +1,74 @@
-How to get the Nebula Electronics DigiTV, Pinnacle PCTV Sat, Twinhan DST + clones working
-=========================================================================================
+How to get the Nebula, PCTV and Twinhan DST cards working
+=========================================================
 
-1) General information
-======================
+This class of cards has a bt878a as the PCI interface, and
+require the bttv driver.
 
-This class of cards has a bt878a chip as the PCI interface.
-The different card drivers require the bttv driver to provide the means
-to access the i2c bus and the gpio pins of the bt8xx chipset.
+Please pay close attention to the warning about the bttv module
+options below for the DST card.
 
-2) Compilation rules for Kernel >= 2.6.12
-=========================================
+1) General informations
+=======================
 
-Enable the following options:
+These drivers require the bttv driver to provide the means to access
+the i2c bus and the gpio pins of the bt8xx chipset.
 
+Because of this, you need to enable
 "Device drivers" => "Multimedia devices"
- => "Video For Linux" => "BT848 Video For Linux"
+  => "Video For Linux" => "BT848 Video For Linux"
+
+Furthermore you need to enable
 "Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
- => "DVB for Linux" "DVB Core Support" "BT8xx based PCI cards"
 => "DVB for Linux" "DVB Core Support" "BT8xx based PCI cards"
 
-3) Loading Modules, described by two approaches
-===============================================
+2) Loading Modules
+==================
 
 In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us, plus the common dvb-bt8xx device driver,
-which is called the backend.
-The frontends for Nebula DigiTV (nxt6000), Pinnacle PCTV Sat (cx24110),
-TwinHan DST + clones (dst and dst-ca) are loaded automatically by the backend.
-For further details about TwinHan DST + clones see /Documentation/dvb/ci.txt.
+i2c communication for us, plus the common dvb-bt8xx device driver.
+The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
+TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
 
-3a) The manual approach
------------------------
+3a) Nebula / Pinnacle PCTV
+--------------------------
 
-Loading modules:
-modprobe bttv
-modprobe dvb-bt8xx
+   $ modprobe bttv (normally bttv is being loaded automatically by kmod)
+   $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
 
-Unloading modules:
-modprobe -r dvb-bt8xx
-modprobe -r bttv
 
-3b) The automatic approach
+3b) TwinHan and Clones
 --------------------------
 
-If not already done by installation, place a line either in
-/etc/modules.conf or in /etc/modprobe.conf containing this text:
-alias char-major-81    bttv
+   $ modprobe bttv i2c_hw=1 card=0x71
+   $ modprobe dvb-bt8xx
+   $ modprobe dst
+
+The value 0x71 will override the PCI type detection for dvb-bt8xx,
+which  is necessary for TwinHan cards.
+
+If you're having an older card (blue color circuit) and card=0x71 locks
+your machine, try using 0x68, too. If that does not work, ask on the
+mailing list.
+
+The DST module takes a couple of useful parameters.
+
+verbose takes values 0 to 4. These values control the verbosity level,
+and can be used to debug also.
+
+verbose=0 means complete disabling of messages
+       1 only error messages are displayed
+       2 notifications are also displayed
+       3 informational messages are also displayed
+       4 debug setting
+
+dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card.
+0x20 means it has a Conditional Access slot.
+
+The autodected values are determined bythe cards 'response
+string' which you can see in your logs e.g.
 
-Then place a line in /etc/modules containing this text:
-dvb-bt8xx
+dst_get_device_id: Recognise [DSTMCI]
 
-Reboot your system and have fun!
 
 --
-Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, Uwe Bugla
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
index 62e0701b542af416092a6a4aa8cafe6f1b04f008..95f0e73b2135a10463476e0fbe789dba62eb2ef5 100644 (file)
@@ -23,7 +23,6 @@ This application requires the following to function properly as of now.
          eg: $ szap -c channels.conf -r "TMC" -x
 
        (b) a channels.conf containing a valid PMT PID
-
          eg: TMC:11996:h:0:27500:278:512:650:321
 
          here 278 is a valid PMT PID. the rest of the values are the
@@ -31,13 +30,7 @@ This application requires the following to function properly as of now.
 
        (c) after running a szap, you have to run ca_zap, for the
          descrambler to function,
-
-         eg: $ ca_zap patched_channels.conf "TMC"
-
-         The patched means a patch to apply to scan, such that scan can
-         generate a channels.conf_with pmt, which has this PMT PID info
-         (NOTE: szap cannot use this channels.conf with the PMT_PID)
-
+         eg: $ ca_zap channels.conf "TMC"
 
        (d) Hopeflly Enjoy your favourite subscribed channel as you do with
          a FTA card.
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs
new file mode 100644 (file)
index 0000000..f90cc66
--- /dev/null
@@ -0,0 +1,14 @@
+Bugs
+====
+
+I currently don't know of any bug. Please do send reports to:
+ - linux-fbdev-devel@lists.sourceforge.net
+ - Knut_Petersen@t-online.de.
+
+
+Untested features
+=================
+
+All LCD stuff is untested. If it worked in tridentfb, it should work in
+cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
+
diff --git a/Documentation/fb/cyblafb/credits b/Documentation/fb/cyblafb/credits
new file mode 100644 (file)
index 0000000..0eb3b44
--- /dev/null
@@ -0,0 +1,7 @@
+Thanks to
+=========
+   *   Alan Hourihane, for writing the X trident driver
+   *   Jani Monoses, for writing the tridentfb driver
+   *   Antonino A. Daplas, for review of the first published
+       version of cyblafb and some code
+   *   Jochen Hein, for testing and a helpfull bug report
diff --git a/Documentation/fb/cyblafb/documentation b/Documentation/fb/cyblafb/documentation
new file mode 100644 (file)
index 0000000..bb1aac0
--- /dev/null
@@ -0,0 +1,17 @@
+Available Documentation
+=======================
+
+Apollo PLE 133 Chipset VT8601A North Bridge Datasheet, Rev. 1.82, October 22,
+2001, available from VIA:
+
+       http://www.viavpsd.com/product/6/15/DS8601A182.pdf
+
+The datasheet is incomplete, some registers that need to be programmed are not
+explained at all and important bits are listed as "reserved". But you really
+need the datasheet to understand the code.  "p. xxx" comments refer to page
+numbers of this document.
+
+XFree/XOrg drivers are available and of good quality, looking at the code
+there is a good idea if the datasheet does not provide enough information
+or if the datasheet seems to be wrong.
+
diff --git a/Documentation/fb/cyblafb/fb.modes b/Documentation/fb/cyblafb/fb.modes
new file mode 100644 (file)
index 0000000..cf4351f
--- /dev/null
@@ -0,0 +1,155 @@
+#
+#   Sample fb.modes file
+#
+#      Provides an incomplete list of working modes for
+#      the cyberblade/i1 graphics core.
+#
+#      The value 4294967256 is used instead of -40. Of course, -40 is not
+#      a really reasonable value, but chip design does not always follow
+#      logic. Believe me, it's ok, and it's the way the BIOS does it.
+#
+#      fbset requires 4294967256 in fb.modes and -40 as an argument to
+#      the -t parameter. That's also not too reasonable, and it might change
+#      in the future or might even be differt for your current version.
+#
+
+mode "640x480-50"
+    geometry 640 480 640 3756 8
+    timings 47619 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-60"
+    geometry 640 480 640 3756 8
+    timings 39682 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-70"
+    geometry 640 480 640 3756 8
+    timings 34013 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-72"
+    geometry 640 480 640 3756 8
+    timings 33068 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-75"
+    geometry 640 480 640 3756 8
+    timings 31746 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-80"
+    geometry 640 480 640 3756 8
+    timings 29761 4294967256 24 17 0 216 3
+endmode
+
+mode "640x480-85"
+    geometry 640 480 640 3756 8
+    timings 28011 4294967256 24 17 0 216 3
+endmode
+
+mode "800x600-50"
+    geometry 800 600 800 3221 8
+    timings 30303 96 24 14 0 136 11
+endmode
+
+mode "800x600-60"
+    geometry 800 600 800 3221 8
+    timings 25252 96 24 14 0 136 11
+endmode
+
+mode "800x600-70"
+    geometry 800 600 800 3221 8
+    timings 21645 96 24 14 0 136 11
+endmode
+
+mode "800x600-72"
+    geometry 800 600 800 3221 8
+    timings 21043 96 24 14 0 136 11
+endmode
+
+mode "800x600-75"
+    geometry 800 600 800 3221 8
+    timings 20202 96 24 14 0 136 11
+endmode
+
+mode "800x600-80"
+    geometry 800 600 800 3221 8
+    timings 18939 96 24 14 0 136 11
+endmode
+
+mode "800x600-85"
+    geometry 800 600 800 3221 8
+    timings 17825 96 24 14 0 136 11
+endmode
+
+mode "1024x768-50"
+    geometry 1024 768 1024 2815 8
+    timings 19054 144 24 29 0 120 3
+endmode
+
+mode "1024x768-60"
+    geometry 1024 768 1024 2815 8
+    timings 15880 144 24 29 0 120 3
+endmode
+
+mode "1024x768-70"
+    geometry 1024 768 1024 2815 8
+    timings 13610 144 24 29 0 120 3
+endmode
+
+mode "1024x768-72"
+    geometry 1024 768 1024 2815 8
+    timings 13232 144 24 29 0 120 3
+endmode
+
+mode "1024x768-75"
+    geometry 1024 768 1024 2815 8
+    timings 12703 144 24 29 0 120 3
+endmode
+
+mode "1024x768-80"
+    geometry 1024 768 1024 2815 8
+    timings 11910 144 24 29 0 120 3
+endmode
+
+mode "1024x768-85"
+    geometry 1024 768 1024 2815 8
+    timings 11209 144 24 29 0 120 3
+endmode
+
+mode "1280x1024-50"
+    geometry 1280 1024 1280 2662 8
+    timings 11114 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-60"
+    geometry 1280 1024 1280 2662 8
+    timings 9262 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-70"
+    geometry 1280 1024 1280 2662 8
+    timings 7939 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-72"
+    geometry 1280 1024 1280 2662 8
+    timings 7719 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-75"
+    geometry 1280 1024 1280 2662 8
+    timings 7410 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-80"
+    geometry 1280 1024 1280 2662 8
+    timings 6946 232 16 39 0 160 3
+endmode
+
+mode "1280x1024-85"
+    geometry 1280 1024 1280 2662 8
+    timings 6538 232 16 39 0 160 3
+endmode
+
diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance
new file mode 100644 (file)
index 0000000..eb4e47a
--- /dev/null
@@ -0,0 +1,80 @@
+Speed
+=====
+
+CyBlaFB is much faster than tridentfb and vesafb. Compare the performance data
+for mode 1280x1024-[8,16,32]@61 Hz.
+
+Test 1: Cat a file with 2000 lines of 0 characters.
+Test 2: Cat a file with 2000 lines of 80 characters.
+Test 3: Cat a file with 2000 lines of 160 characters.
+
+All values show system time use in seconds, kernel 2.6.12 was used for
+the measurements. 2.6.13 is a bit slower, 2.6.14 hopefully will include a
+patch that speeds up kernel bitblitting a lot ( > 20%).
+
++-----------+-----------------------------------------------------+
+|          |                   not accelerated                   |
+| TRIDENTFB +-----------------+-----------------+-----------------+
+| of 2.6.12 |     8 bpp      |     16 bpp      |     32 bpp      |
+|          | noypan |   ypan | noypan |   ypan | noypan |   ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+|    Test 1 |  4.31 |   4.33 |   6.05 |  12.81 |  ----  |  ----  |
+|    Test 2 |  67.94 |  5.44 | 123.16 |  14.79 |  ----  |  ----  |
+|    Test 3 | 131.36 |  6.55 | 240.12 |  16.76 |  ----  |  ----  |
++-----------+--------+--------+--------+--------+--------+--------+
+|  Comments |                |                 | completely bro- |
+|          |                 |                 | ken, monitor    |
+|          |                 |                 | switches off    |
++-----------+-----------------+-----------------+-----------------+
+
+
++-----------+-----------------------------------------------------+
+|          |                     accelerated                     |
+| TRIDENTFB +-----------------+-----------------+-----------------+
+| of 2.6.12 |     8 bpp      |     16 bpp      |     32 bpp      |
+|          | noypan |   ypan | noypan |   ypan | noypan |   ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+|    Test 1 |  ----  | ----  |  20.62 |   1.22 |  ----  |  ----  |
+|    Test 2 |  ----  | ----  |  22.61 |   3.19 |  ----  |  ----  |
+|    Test 3 |  ----  | ----  |  24.59 |   5.16 |  ----  |  ----  |
++-----------+--------+--------+--------+--------+--------+--------+
+|  Comments | broken, writing | broken, ok only | completely bro- |
+|          | to wrong places | if bgcolor is   | ken, monitor    |
+|          | on screen + bug | black, bug in   | switches off    |
+|          | in fillrect()   | fillrect()      |                 |
++-----------+-----------------+-----------------+-----------------+
+
+
++-----------+-----------------------------------------------------+
+|          |                   not accelerated                   |
+|   VESAFB  +-----------------+-----------------+-----------------+
+| of 2.6.12 |     8 bpp      |     16 bpp      |     32 bpp      |
+|          | noypan |   ypan | noypan |   ypan | noypan |   ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+|    Test 1 |  4.26 |   3.76 |   5.99 |   7.23 |  ----  |  ----  |
+|    Test 2 |  65.65 |  4.89 | 120.88 |   9.08 |  ----  |  ----  |
+|    Test 3 | 126.91 |  5.94 | 235.77 |  11.03 |  ----  |  ----  |
++-----------+--------+--------+--------+--------+--------+--------+
+|  Comments | vga=0x307       | vga=0x31a      | vga=0x31b not   |
+|          | fh=80kHz        | fh=80kHz        | supported by    |
+|          | fv=75kHz        | fv=75kHz        | video BIOS and  |
+|          |                 |                 | hardware        |
++-----------+-----------------+-----------------+-----------------+
+
+
++-----------+-----------------------------------------------------+
+|          |                     accelerated                     |
+|  CYBLAFB  +-----------------+-----------------+-----------------+
+|          |      8 bpp      |     16 bpp      |     32 bpp      |
+|          | noypan |   ypan | noypan |   ypan | noypan |   ypan |
++-----------+--------+--------+--------+--------+--------+--------+
+|    Test 1 |  8.02 |   0.23 |  19.04 |   0.61 |  57.12 |   2.74 |
+|    Test 2 |  8.38 |   0.55 |  19.39 |   0.92 |  57.54 |   3.13 |
+|    Test 3 |  8.73 |   0.86 |  19.74 |   1.24 |  57.95 |   3.51 |
++-----------+--------+--------+--------+--------+--------+--------+
+|  Comments |                |                 |                 |
+|          |                 |                 |                 |
+|          |                 |                 |                 |
+|          |                 |                 |                 |
++-----------+-----------------+-----------------+-----------------+
+
diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo
new file mode 100644 (file)
index 0000000..80fb2f8
--- /dev/null
@@ -0,0 +1,32 @@
+TODO / Missing features
+=======================
+
+Verify LCD stuff               "stretch" and "center" options are
+                               completely untested ... this code needs to be
+                               verified. As I don't have access to such
+                               hardware, please contact me if you are
+                               willing run some tests.
+
+Interlaced video modes         The reason that interleaved
+                               modes are disabled is that I do not know
+                               the meaning of the vertical interlace
+                               parameter. Also the datasheet mentions a
+                               bit d8 of a horizontal interlace parameter,
+                               but nowhere the lower 8 bits. Please help
+                               if you can.
+
+low-res double scan modes      Who needs it?
+
+accelerated color blitting     Who needs it? The console driver does use color
+                               blitting for nothing but drawing the penguine,
+                               everything else is done using color expanding
+                               blitting of 1bpp character bitmaps.
+
+xpanning                       Who needs it?
+
+ioctls                         Who needs it?
+
+TV-out                         Will be done later
+
+???                            Feel free to contact me if you have any
+                               feature requests
diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage
new file mode 100644 (file)
index 0000000..e627c8f
--- /dev/null
@@ -0,0 +1,206 @@
+CyBlaFB is a framebuffer driver for the Cyberblade/i1 graphics core integrated
+into the VIA Apollo PLE133 (aka vt8601) south bridge. It is developed and
+tested using a VIA EPIA 5000 board.
+
+Cyblafb - compiled into the kernel or as a module?
+==================================================
+
+You might compile cyblafb either as a module or compile it permanently into the
+kernel.
+
+Unless you have a real reason to do so you should not compile both vesafb and
+cyblafb permanently into the kernel. It's possible and it helps during the
+developement cycle, but it's useless and will at least block some otherwise
+usefull memory for ordinary users.
+
+Selecting Modes
+===============
+
+       Startup Mode
+       ============
+
+       First of all, you might use the "vga=???" boot parameter as it is
+       documented in vesafb.txt and svga.txt. Cyblafb will detect the video
+       mode selected and will use the geometry and timings found by
+       inspecting the hardware registers.
+
+               video=cyblafb vga=0x317
+
+       Alternatively you might use a combination of the mode, ref and bpp
+       parameters. If you compiled the driver into the kernel, add something
+       like this to the kernel command line:
+
+               video=cyblafb:1280x1024,bpp=16,ref=50 ...
+
+       If you compiled the driver as a module, the same mode would be
+       selected by the following command:
+
+               modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ...
+
+       None of the modes possible to select as startup modes are affected by
+       the problems described at the end of the next subsection.
+
+       Mode changes using fbset
+       ========================
+
+       You might use fbset to change the video mode, see "man fbset". Cyblafb
+       generally does assume that you know what you are doing. But it does
+       some checks, especially those that are needed to prevent you from
+       damaging your hardware.
+
+               - only 8, 16, 24 and 32 bpp video modes are accepted
+               - interlaced video modes are not accepted
+               - double scan video modes are not accepted
+               - if a flat panel is found, cyblafb does not allow you
+                 to program a resolution higher than the physical
+                 resolution of the flat panel monitor
+               - cyblafb does not allow xres to differ from xres_virtual
+               - cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp
+                 and (currently) 24 bit modes use a doubled vclk internally,
+                 the dotclock limit as seen by fbset is 115 MHz for those
+                 modes and 230 MHz for 8 and 16 bpp modes.
+
+       Any request that violates the rules given above will be ignored and
+       fbset will return an error.
+
+       If you program a virtual y resolution higher than the hardware limit,
+       cyblafb will silently decrease that value to the highest possible
+       value.
+
+       Attempts to disable acceleration are ignored.
+
+       Some video modes that should work do not work as expected. If you use
+       the standard fb.modes, fbset 640x480-60 will program that mode, but
+       you will see a vertical area, about two characters wide, with only
+       much darker characters than the other characters on the screen.
+       Cyblafb does allow that mode to be set, as it does not violate the
+       official specifications. It would need a lot of code to reliably sort
+       out all invalid modes, playing around with the margin values will
+       give a valid mode quickly. And if cyblafb would detect such an invalid
+       mode, should it silently alter the requested values or should it
+       report an error? Both options have some pros and cons. As stated
+       above, none of the startup modes are affected, and if you set
+       verbosity to 1 or higher, cyblafb will print the fbset command that
+       would be needed to program that mode using fbset.
+
+
+Other Parameters
+================
+
+
+crt            don't autodetect, assume monitor connected to
+               standard VGA connector
+
+fp             don't autodetect, assume flat panel display
+               connected to flat panel monitor interface
+
+nativex        inform driver about native x resolution of
+               flat panel monitor connected to special
+               interface (should be autodetected)
+
+stretch        stretch image to adapt low resolution modes to
+               higer resolutions of flat panel monitors
+               connected to special interface
+
+center         center image to adapt low resolution modes to
+               higer resolutions of flat panel monitors
+               connected to special interface
+
+memsize        use if autodetected memsize is wrong ...
+               should never be necessary
+
+nopcirr        disable PCI read retry
+nopciwr        disable PCI write retry
+nopcirb        disable PCI read bursts
+nopciwb        disable PCI write bursts
+
+bpp            bpp for specified modes
+               valid values: 8 || 16 || 24 || 32
+
+ref            refresh rate for specified mode
+               valid values: 50 <= ref <= 85
+
+mode           640x480 or 800x600 or 1024x768 or 1280x1024
+               if not specified, the startup mode will be detected
+               and used, so you might also use the vga=??? parameter
+               described in vesafb.txt. If you do not specify a mode,
+               bpp and ref parameters are ignored.
+
+verbosity      0 is the default, increase to at least 2 for every
+               bug report!
+
+vesafb         allows cyblafb to be loaded after vesafb has been
+               loaded. See sections "Module unloading ...".
+
+
+Development hints
+=================
+
+It's much faster do compile a module and to load the new version after
+unloading the old module than to compile a new kernel and to reboot. So if you
+try to work on cyblafb, it might be a good idea to use cyblafb as a module.
+In real life, fast often means dangerous, and that's also the case here. If
+you introduce a serious bug when cyblafb is compiled into the kernel, the
+kernel will lock or oops with a high probability before the file system is
+mounted, and the danger for your data is low. If you load a broken own version
+of cyblafb on a running system, the danger for the integrity of the file
+system is much higher as you might need a hard reset afterwards. Decide
+yourself.
+
+Module unloading, the vfb method
+================================
+
+If you want to unload/reload cyblafb using the virtual framebuffer, you need
+to enable vfb support in the kernel first. After that, load the modules as
+shown below:
+
+       modprobe vfb vfb_enable=1
+       modprobe fbcon
+       modprobe cyblafb
+       fbset -fb /dev/fb1 1280x1024-60 -vyres 2662
+       con2fb /dev/fb1 /dev/tty1
+       ...
+
+If you now made some changes to cyblafb and want to reload it, you might do it
+as show below:
+
+       con2fb /dev/fb0 /dev/tty1
+       ...
+       rmmod cyblafb
+       modprobe cyblafb
+       con2fb /dev/fb1 /dev/tty1
+       ...
+
+Of course, you might choose another mode, and most certainly you also want to
+map some other /dev/tty* to the real framebuffer device. You might also choose
+to compile fbcon as a kernel module or place it permanently in the kernel.
+
+I do not know of any way to unload fbcon, and fbcon will prevent the
+framebuffer device loaded first from unloading. [If there is a way, then
+please add a description here!]
+
+Module unloading, the vesafb method
+===================================
+
+Configure the kernel:
+
+       <*> Support for frame buffer devices
+       [*]   VESA VGA graphics support
+       <M>   Cyberblade/i1 support
+
+Add e.g. "video=vesafb:ypan vga=0x307" to the kernel parameters. The ypan
+parameter is important, choose any vga parameter you like as long as it is
+a graphics mode.
+
+After booting, load cyblafb without any mode and bpp parameter and assign
+cyblafb to individual ttys using con2fb, e.g.:
+
+       modprobe cyblafb vesafb=1
+       con2fb /dev/fb1 /dev/tty1
+
+Unloading cyblafb works without problems after you assign vesafb to all
+ttys again, e.g.:
+
+       con2fb /dev/fb0 /dev/tty1
+       rmmod cyblafb
+
diff --git a/Documentation/fb/cyblafb/whycyblafb b/Documentation/fb/cyblafb/whycyblafb
new file mode 100644 (file)
index 0000000..a123bc1
--- /dev/null
@@ -0,0 +1,85 @@
+I tried the following framebuffer drivers:
+
+       - TRIDENTFB is full of bugs. Acceleration is broken for Blade3D
+         graphics cores like the cyberblade/i1. It claims to support a great
+         number of devices, but documentation for most of these devices is
+         unfortunately not available. There is _no_ reason to use tridentfb
+         for cyberblade/i1 + CRT users. VESAFB is faster, and the one
+         advantage, mode switching, is broken in tridentfb.
+
+       - VESAFB is used by many distributions as a standard. Vesafb does
+         not support mode switching. VESAFB is a bit faster than the working
+         configurations of TRIDENTFB, but it is still too slow, even if you
+         use ypan.
+
+       - EPIAFB (you'll find it on sourceforge) supports the Cyberblade/i1
+         graphics core, but it still has serious bugs and developement seems
+         to have stopped. This is the one driver with TV-out support. If you
+         do need this feature, try epiafb.
+
+None of these drivers was a real option for me.
+
+I believe that is unreasonable to change code that announces to support 20
+devices if I only have more or less sufficient documentation for exactly one
+of these. The risk of breaking device foo while fixing device bar is too high.
+
+So I decided to start CyBlaFB as a stripped down tridentfb.
+
+All code specific to other Trident chips has been removed. After that there
+were a lot of cosmetic changes to increase the readability of the code. All
+register names were changed to those mnemonics used in the datasheet. Function
+and macro names were changed if they hindered easy understanding of the code.
+
+After that I debugged the code and implemented some new features. I'll try to
+give a little summary of the main changes:
+
+       - calculation of vertical and horizontal timings was fixed
+
+       - video signal quality has been improved dramatically
+
+       - acceleration:
+
+               - fillrect and copyarea were fixed and reenabled
+
+               - color expanding imageblit was newly implemented, color
+                 imageblit (only used to draw the penguine) still uses the
+                 generic code.
+
+               - init of the acceleration engine was improved and moved to a
+                 place where it really works ...
+
+               - sync function has a timeout now and tries to reset and
+                 reinit the accel engine if necessary
+
+               - fewer slow copyarea calls when doing ypan scrolling by using
+                 undocumented bit d21 of screen start address stored in
+                 CR2B[5]. BIOS does use it also, so this should be safe.
+
+       - cyblafb rejects any attempt to set modes that would cause vclk
+         values above reasonable 230 MHz. 32bit modes use a clock
+         multiplicator of 2, so fbset does show the correct values for
+         pixclock but not for vclk in this case. The fbset limit is 115 MHz
+         for 32 bpp modes.
+
+       - cyblafb rejects modes known to be broken or unimplemented (all
+         interlaced modes, all doublescan modes for now)
+
+       - cyblafb now works independant of the video mode in effect at startup
+         time (tridentfb does not init all needed registers to reasonable
+         values)
+
+       - switching between video modes does work reliably now
+
+       - the first video mode now is the one selected on startup using the
+         vga=???? mechanism or any of
+               - 640x480, 800x600, 1024x768, 1280x1024
+               - 8, 16, 24 or 32 bpp
+               - refresh between 50 Hz and 85 Hz, 1 Hz steps (1280x1024-32
+                 is limited to 63Hz)
+
+       - pci retry and pci burst mode are settable (try to disable if you
+         experience latency problems)
+
+       - built as a module cyblafb might be unloaded and reloaded using
+         the vfb module and con2vt or might be used together with vesafb
+
index fd68b162e4a13ce7cbf028405a14724224542e1f..4f0d6bc789ef0fadf101eaa362fa3d829dc8a588 100644 (file)
@@ -5,6 +5,7 @@ Intel 810/815 Framebuffer driver
        March 17, 2002
 
        First Released: July 2001
+       Last Update:    September 12, 2005
 ================================================================
 
 A. Introduction
@@ -44,6 +45,8 @@ B.  Features
 
        - Hardware Cursor Support
  
+       - Supports EDID probing either by DDC/I2C or through the BIOS
+
 C.  List of available options
        
    a. "video=i810fb"  
@@ -52,14 +55,17 @@ C.  List of available options
        Recommendation: required
  
    b. "xres:<value>"  
-       select horizontal resolution in pixels
+       select horizontal resolution in pixels. (This parameter will be
+       ignored if 'mode_option' is specified.  See 'o' below).
 
        Recommendation: user preference 
        (default = 640)
 
    c. "yres:<value>"
        select vertical resolution in scanlines. If Discrete Video Timings
-       is enabled, this will be ignored and computed as 3*xres/4.  
+       is enabled, this will be ignored and computed as 3*xres/4.  (This
+       parameter will be ignored if 'mode_option' is specified.  See 'o'
+       below)  
 
        Recommendation: user preference
        (default = 480)
@@ -86,7 +92,8 @@ C.  List of available options
    g. "hsync1/hsync2:<value>" 
        select the minimum and maximum Horizontal Sync Frequency of the 
        monitor in KHz.  If a using a fixed frequency monitor, hsync1 must 
-       be equal to hsync2. 
+       be equal to hsync2. If EDID probing is successful, these will be
+       ignored and values will be taken from the EDID block.
 
        Recommendation: check monitor manual for correct values
        default (29/30)
@@ -94,7 +101,8 @@ C.  List of available options
    h. "vsync1/vsync2:<value>" 
        select the minimum and maximum Vertical Sync Frequency of the monitor
        in Hz. You can also use this option to lock your monitor's refresh 
-       rate.
+       rate. If EDID probing is successful, these will be ignored and values
+       will be taken from the EDID block.
 
        Recommendation: check monitor manual for correct values
        (default = 60/60)
@@ -154,7 +162,11 @@ C.  List of available options
 
        Recommendation: do not set
        (default = not set)
-                       
+   o. <xres>x<yres>[-<bpp>][@<refresh>]
+       The driver will now accept specification of boot mode option.  If this
+       is specified, the options 'xres' and 'yres' will be ignored. See
+       Documentation/fb/modedb.txt for usage.
+
 D. Kernel booting
 
 Separate each option/option-pair by commas (,) and the option from its value
@@ -176,7 +188,10 @@ will be computed based on the hsync1/hsync2 and vsync1/vsync2 values.
 
 IMPORTANT:
 You must include hsync1, hsync2, vsync1 and vsync2 to enable video modes
-better than 640x480 at 60Hz.
+better than 640x480 at 60Hz. HOWEVER, if your chipset/display combination
+supports I2C and has an EDID block, you can safely exclude hsync1, hsync2,
+vsync1 and vsync2 parameters.  These parameters will be taken from the EDID
+block.
 
 E.  Module options
        
@@ -217,32 +232,21 @@ F.  Setup
           This is required.  The option is under "Character Devices"
 
        d. Under "Graphics Support", select "Intel 810/815" either statically
-          or as a module.  Choose "use VESA GTF for video timings"  if you 
-          need to maximize the capability of your display.  To be on the 
+          or as a module.  Choose "use VESA Generalized Timing Formula" if
+          you need to maximize the capability of your display.  To be on the 
           safe side, you can leave this unselected.  
   
-        e. If you want a framebuffer console, enable it under "Console 
+       e. If you want support for DDC/I2C probing (Plug and Play Displays),
+          set 'Enable DDC Support' to 'y'. To make this option appear, set
+          'use VESA Generalized Timing Formula' to 'y'.
+
+        f. If you want a framebuffer console, enable it under "Console 
           Drivers"
 
-       f. Compile your kernel. 
+       g. Compile your kernel. 
                
-       g. Load the driver as described in section D and E.
+       h. Load the driver as described in section D and E.
        
-       Optional:       
-       h.  If you are going to run XFree86 with its native drivers, the 
-           standard XFree86 4.1.0 and 4.2.0 drivers should work as is.
-            However, there's a bug in the XFree86 i810 drivers.  It attempts 
-           to use XAA even when switched to the console. This will crash
-           your server. I have a fix at this site:  
-           
-           http://i810fb.sourceforge.net.  
-
-           You can either use the patch, or just replace 
-           
-            /usr/X11R6/lib/modules/drivers/i810_drv.o
-
-           with the one provided at the website.       
-
        i.  Try the DirectFB (http://www.directfb.org) + the i810 gfxdriver
            patch to see the chipset in action (or inaction :-).
 
index e04458b319d576ac076a0e09211108a8b4390f7b..4fcdb4cf4cca922c91d7ff699154c5ecae39778d 100644 (file)
@@ -20,12 +20,83 @@ in a video= option, fbmem considers that to be a global video mode option.
 
 Valid mode specifiers (mode_option argument):
 
-    <xres>x<yres>[-<bpp>][@<refresh>]
+    <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m]
     <name>[-<bpp>][@<refresh>]
 
 with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
 Things between square brackets are optional.
 
+If 'M' is specified in the mode_option argument (after <yres> and before
+<bpp> and <refresh>, if specified) the timings will be calculated using
+VESA(TM) Coordinated Video Timings instead of looking up the mode from a table.
+If 'R' is specified, do a 'reduced blanking' calculation for digital displays.
+If 'i' is specified, calculate for an interlaced mode.  And if 'm' is
+specified, add margins to the calculation (1.8% of xres rounded down to 8
+pixels and 1.8% of yres).
+
+       Sample usage: 1024x768M@60m - CVT timing with margins
+
+***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
+
+What is the VESA(TM) Coordinated Video Timings (CVT)?
+
+From the VESA(TM) Website:
+
+     "The purpose of CVT is to provide a method for generating a consistent
+      and coordinated set of standard formats, display refresh rates, and
+      timing specifications for computer display products, both those
+      employing CRTs, and those using other display technologies. The
+      intention of CVT is to give both source and display manufacturers a
+      common set of tools to enable new timings to be developed in a
+      consistent manner that ensures greater compatibility."
+
+This is the third standard approved by VESA(TM) concerning video timings.  The
+first was the Discrete Video Timings (DVT) which is  a collection of
+pre-defined modes approved by VESA(TM).  The second is the Generalized Timing
+Formula (GTF) which is an algorithm to calculate the timings, given the
+pixelclock, the horizontal sync frequency, or the vertical refresh rate.
+
+The GTF is limited by the fact that it is designed mainly for CRT displays.
+It artificially increases the pixelclock because of its high blanking
+requirement. This is inappropriate for digital display interface with its high
+data rate which requires that it conserves the pixelclock as much as possible.
+Also, GTF does not take into account the aspect ratio of the display.
+
+The CVT addresses these limitations.  If used with CRT's, the formula used
+is a derivation of GTF with a few modifications.  If used with digital
+displays, the "reduced blanking" calculation can be used.
+
+From the framebuffer subsystem perspective, new formats need not be added
+to the global mode database whenever a new mode is released by display
+manufacturers. Specifying for CVT will work for most, if not all, relatively
+new CRT displays and probably with most flatpanels, if 'reduced blanking'
+calculation is specified.  (The CVT compatibility of the display can be
+determined from its EDID. The version 1.3 of the EDID has extra 128-byte
+blocks where additional timing information is placed.  As of this time, there
+is no support yet in the layer to parse this additional blocks.)
+
+CVT also introduced a new naming convention (should be seen from dmesg output):
+
+    <pix>M<a>[-R]
+
+    where: pix = total amount of pixels in MB (xres x yres)
+           M   = always present
+           a   = aspect ratio (3 - 4:3; 4 - 5:4; 9 - 15:9, 16:9; A - 16:10)
+          -R   = reduced blanking
+
+         example:  .48M3-R - 800x600 with reduced blanking
+
+Note: VESA(TM) has restrictions on what is a standard CVT timing:
+
+      - aspect ratio can only be one of the above values
+      - acceptable refresh rates are 50, 60, 70 or 85 Hz only
+      - if reduced blanking, the refresh rate must be at 60Hz
+
+If one of the above are not satisfied, the kernel will print a warning but the
+timings will still be calculated.
+
+***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo ***** oOo *****
+
 To find a suitable video mode, you just call
 
 int __init fb_find_mode(struct fb_var_screeninfo *var,
index 5f95d4b3cab1a4f6625f65431a720703e1ce2a05..784e08c1c80a308b9916a4a1f360380482761603 100644 (file)
@@ -17,14 +17,6 @@ Who: Greg Kroah-Hartman <greg@kroah.com>
 
 ---------------------------
 
-What:  ACPI S4bios support
-When:  May 2005
-Why:   Noone uses it, and it probably does not work, anyway. swsusp is
-       faster, more reliable, and people are actually using it.
-Who:   Pavel Machek <pavel@suse.cz>
-
----------------------------
-
 What:  io_remap_page_range() (macro or function)
 When:  September 2005
 Why:   Replaced by io_remap_pfn_range() which allows more memory space
diff --git a/Documentation/filesystems/files.txt b/Documentation/filesystems/files.txt
new file mode 100644 (file)
index 0000000..8c206f4
--- /dev/null
@@ -0,0 +1,123 @@
+File management in the Linux kernel
+-----------------------------------
+
+This document describes how locking for files (struct file)
+and file descriptor table (struct files) works.
+
+Up until 2.6.12, the file descriptor table has been protected
+with a lock (files->file_lock) and reference count (files->count).
+->file_lock protected accesses to all the file related fields
+of the table. ->count was used for sharing the file descriptor
+table between tasks cloned with CLONE_FILES flag. Typically
+this would be the case for posix threads. As with the common
+refcounting model in the kernel, the last task doing
+a put_files_struct() frees the file descriptor (fd) table.
+The files (struct file) themselves are protected using
+reference count (->f_count).
+
+In the new lock-free model of file descriptor management,
+the reference counting is similar, but the locking is
+based on RCU. The file descriptor table contains multiple
+elements - the fd sets (open_fds and close_on_exec, the
+array of file pointers, the sizes of the sets and the array
+etc.). In order for the updates to appear atomic to
+a lock-free reader, all the elements of the file descriptor
+table are in a separate structure - struct fdtable.
+files_struct contains a pointer to struct fdtable through
+which the actual fd table is accessed. Initially the
+fdtable is embedded in files_struct itself. On a subsequent
+expansion of fdtable, a new fdtable structure is allocated
+and files->fdtab points to the new structure. The fdtable
+structure is freed with RCU and lock-free readers either
+see the old fdtable or the new fdtable making the update
+appear atomic. Here are the locking rules for
+the fdtable structure -
+
+1. All references to the fdtable must be done through
+   the files_fdtable() macro :
+
+       struct fdtable *fdt;
+
+       rcu_read_lock();
+
+       fdt = files_fdtable(files);
+       ....
+       if (n <= fdt->max_fds)
+               ....
+       ...
+       rcu_read_unlock();
+
+   files_fdtable() uses rcu_dereference() macro which takes care of
+   the memory barrier requirements for lock-free dereference.
+   The fdtable pointer must be read within the read-side
+   critical section.
+
+2. Reading of the fdtable as described above must be protected
+   by rcu_read_lock()/rcu_read_unlock().
+
+3. For any update to the the fd table, files->file_lock must
+   be held.
+
+4. To look up the file structure given an fd, a reader
+   must use either fcheck() or fcheck_files() APIs. These
+   take care of barrier requirements due to lock-free lookup.
+   An example :
+
+       struct file *file;
+
+       rcu_read_lock();
+       file = fcheck(fd);
+       if (file) {
+               ...
+       }
+       ....
+       rcu_read_unlock();
+
+5. Handling of the file structures is special. Since the look-up
+   of the fd (fget()/fget_light()) are lock-free, it is possible
+   that look-up may race with the last put() operation on the
+   file structure. This is avoided using the rcuref APIs
+   on ->f_count :
+
+       rcu_read_lock();
+       file = fcheck_files(files, fd);
+       if (file) {
+               if (rcuref_inc_lf(&file->f_count))
+                       *fput_needed = 1;
+               else
+               /* Didn't get the reference, someone's freed */
+                       file = NULL;
+       }
+       rcu_read_unlock();
+       ....
+       return file;
+
+   rcuref_inc_lf() detects if refcounts is already zero or
+   goes to zero during increment. If it does, we fail
+   fget()/fget_light().
+
+6. Since both fdtable and file structures can be looked up
+   lock-free, they must be installed using rcu_assign_pointer()
+   API. If they are looked up lock-free, rcu_dereference()
+   must be used. However it is advisable to use files_fdtable()
+   and fcheck()/fcheck_files() which take care of these issues.
+
+7. While updating, the fdtable pointer must be looked up while
+   holding files->file_lock. If ->file_lock is dropped, then
+   another thread expand the files thereby creating a new
+   fdtable and making the earlier fdtable pointer stale.
+   For example :
+
+       spin_lock(&files->file_lock);
+       fd = locate_fd(files, file, start);
+       if (fd >= 0) {
+               /* locate_fd() may have expanded fdtable, load the ptr */
+               fdt = files_fdtable(files);
+               FD_SET(fd, fdt->open_fds);
+               FD_CLR(fd, fdt->close_on_exec);
+               spin_unlock(&files->file_lock);
+       .....
+
+   Since locate_fd() can drop ->file_lock (and reacquire ->file_lock),
+   the fdtable pointer (fdt) must be loaded after locate_fd().
+
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
new file mode 100644 (file)
index 0000000..6b5741e
--- /dev/null
@@ -0,0 +1,315 @@
+Definitions
+~~~~~~~~~~~
+
+Userspace filesystem:
+
+  A filesystem in which data and metadata are provided by an ordinary
+  userspace process.  The filesystem can be accessed normally through
+  the kernel interface.
+
+Filesystem daemon:
+
+  The process(es) providing the data and metadata of the filesystem.
+
+Non-privileged mount (or user mount):
+
+  A userspace filesystem mounted by a non-privileged (non-root) user.
+  The filesystem daemon is running with the privileges of the mounting
+  user.  NOTE: this is not the same as mounts allowed with the "user"
+  option in /etc/fstab, which is not discussed here.
+
+Mount owner:
+
+  The user who does the mounting.
+
+User:
+
+  The user who is performing filesystem operations.
+
+What is FUSE?
+~~~~~~~~~~~~~
+
+FUSE is a userspace filesystem framework.  It consists of a kernel
+module (fuse.ko), a userspace library (libfuse.*) and a mount utility
+(fusermount).
+
+One of the most important features of FUSE is allowing secure,
+non-privileged mounts.  This opens up new possibilities for the use of
+filesystems.  A good example is sshfs: a secure network filesystem
+using the sftp protocol.
+
+The userspace library and utilities are available from the FUSE
+homepage:
+
+  http://fuse.sourceforge.net/
+
+Mount options
+~~~~~~~~~~~~~
+
+'fd=N'
+
+  The file descriptor to use for communication between the userspace
+  filesystem and the kernel.  The file descriptor must have been
+  obtained by opening the FUSE device ('/dev/fuse').
+
+'rootmode=M'
+
+  The file mode of the filesystem's root in octal representation.
+
+'user_id=N'
+
+  The numeric user id of the mount owner.
+
+'group_id=N'
+
+  The numeric group id of the mount owner.
+
+'default_permissions'
+
+  By default FUSE doesn't check file access permissions, the
+  filesystem is free to implement it's access policy or leave it to
+  the underlying file access mechanism (e.g. in case of network
+  filesystems).  This option enables permission checking, restricting
+  access based on file mode.  This is option is usually useful
+  together with the 'allow_other' mount option.
+
+'allow_other'
+
+  This option overrides the security measure restricting file access
+  to the user mounting the filesystem.  This option is by default only
+  allowed to root, but this restriction can be removed with a
+  (userspace) configuration option.
+
+'max_read=N'
+
+  With this option the maximum size of read operations can be set.
+  The default is infinite.  Note that the size of read requests is
+  limited anyway to 32 pages (which is 128kbyte on i386).
+
+How do non-privileged mounts work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since the mount() system call is a privileged operation, a helper
+program (fusermount) is needed, which is installed setuid root.
+
+The implication of providing non-privileged mounts is that the mount
+owner must not be able to use this capability to compromise the
+system.  Obvious requirements arising from this are:
+
+ A) mount owner should not be able to get elevated privileges with the
+    help of the mounted filesystem
+
+ B) mount owner should not get illegitimate access to information from
+    other users' and the super user's processes
+
+ C) mount owner should not be able to induce undesired behavior in
+    other users' or the super user's processes
+
+How are requirements fulfilled?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ A) The mount owner could gain elevated privileges by either:
+
+     1) creating a filesystem containing a device file, then opening
+       this device
+
+     2) creating a filesystem containing a suid or sgid application,
+       then executing this application
+
+    The solution is not to allow opening device files and ignore
+    setuid and setgid bits when executing programs.  To ensure this
+    fusermount always adds "nosuid" and "nodev" to the mount options
+    for non-privileged mounts.
+
+ B) If another user is accessing files or directories in the
+    filesystem, the filesystem daemon serving requests can record the
+    exact sequence and timing of operations performed.  This
+    information is otherwise inaccessible to the mount owner, so this
+    counts as an information leak.
+
+    The solution to this problem will be presented in point 2) of C).
+
+ C) There are several ways in which the mount owner can induce
+    undesired behavior in other users' processes, such as:
+
+     1) mounting a filesystem over a file or directory which the mount
+        owner could otherwise not be able to modify (or could only
+        make limited modifications).
+
+        This is solved in fusermount, by checking the access
+        permissions on the mountpoint and only allowing the mount if
+        the mount owner can do unlimited modification (has write
+        access to the mountpoint, and mountpoint is not a "sticky"
+        directory)
+
+     2) Even if 1) is solved the mount owner can change the behavior
+        of other users' processes.
+
+         i) It can slow down or indefinitely delay the execution of a
+           filesystem operation creating a DoS against the user or the
+           whole system.  For example a suid application locking a
+           system file, and then accessing a file on the mount owner's
+           filesystem could be stopped, and thus causing the system
+           file to be locked forever.
+
+         ii) It can present files or directories of unlimited length, or
+           directory structures of unlimited depth, possibly causing a
+           system process to eat up diskspace, memory or other
+           resources, again causing DoS.
+
+       The solution to this as well as B) is not to allow processes
+       to access the filesystem, which could otherwise not be
+       monitored or manipulated by the mount owner.  Since if the
+       mount owner can ptrace a process, it can do all of the above
+       without using a FUSE mount, the same criteria as used in
+       ptrace can be used to check if a process is allowed to access
+       the filesystem or not.
+
+       Note that the ptrace check is not strictly necessary to
+       prevent B/2/i, it is enough to check if mount owner has enough
+       privilege to send signal to the process accessing the
+       filesystem, since SIGSTOP can be used to get a similar effect.
+
+I think these limitations are unacceptable?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If a sysadmin trusts the users enough, or can ensure through other
+measures, that system processes will never enter non-privileged
+mounts, it can relax the last limitation with a "user_allow_other"
+config option.  If this config option is set, the mounting user can
+add the "allow_other" mount option which disables the check for other
+users' processes.
+
+Kernel - userspace interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following diagram shows how a filesystem operation (in this
+example unlink) is performed in FUSE.
+
+NOTE: everything in this description is greatly simplified
+
+ |  "rm /mnt/fuse/file"               |  FUSE filesystem daemon
+ |                                    |
+ |                                    |  >sys_read()
+ |                                    |    >fuse_dev_read()
+ |                                    |      >request_wait()
+ |                                    |        [sleep on fc->waitq]
+ |                                    |
+ |  >sys_unlink()                     |
+ |    >fuse_unlink()                  |
+ |      [get request from             |
+ |       fc->unused_list]             |
+ |      >request_send()               |
+ |        [queue req on fc->pending]  |
+ |        [wake up fc->waitq]         |        [woken up]
+ |        >request_wait_answer()      |
+ |          [sleep on req->waitq]     |
+ |                                    |      <request_wait()
+ |                                    |      [remove req from fc->pending]
+ |                                    |      [copy req to read buffer]
+ |                                    |      [add req to fc->processing]
+ |                                    |    <fuse_dev_read()
+ |                                    |  <sys_read()
+ |                                    |
+ |                                    |  [perform unlink]
+ |                                    |
+ |                                    |  >sys_write()
+ |                                    |    >fuse_dev_write()
+ |                                    |      [look up req in fc->processing]
+ |                                    |      [remove from fc->processing]
+ |                                    |      [copy write buffer to req]
+ |          [woken up]                |      [wake up req->waitq]
+ |                                    |    <fuse_dev_write()
+ |                                    |  <sys_write()
+ |        <request_wait_answer()      |
+ |      <request_send()               |
+ |      [add request to               |
+ |       fc->unused_list]             |
+ |    <fuse_unlink()                  |
+ |  <sys_unlink()                     |
+
+There are a couple of ways in which to deadlock a FUSE filesystem.
+Since we are talking about unprivileged userspace programs,
+something must be done about these.
+
+Scenario 1 -  Simple deadlock
+-----------------------------
+
+ |  "rm /mnt/fuse/file"               |  FUSE filesystem daemon
+ |                                    |
+ |  >sys_unlink("/mnt/fuse/file")     |
+ |    [acquire inode semaphore        |
+ |     for "file"]                    |
+ |    >fuse_unlink()                  |
+ |      [sleep on req->waitq]         |
+ |                                    |  <sys_read()
+ |                                    |  >sys_unlink("/mnt/fuse/file")
+ |                                    |    [acquire inode semaphore
+ |                                    |     for "file"]
+ |                                    |    *DEADLOCK*
+
+The solution for this is to allow requests to be interrupted while
+they are in userspace:
+
+ |      [interrupted by signal]       |
+ |    <fuse_unlink()                  |
+ |    [release semaphore]             |    [semaphore acquired]
+ |  <sys_unlink()                     |
+ |                                    |    >fuse_unlink()
+ |                                    |      [queue req on fc->pending]
+ |                                    |      [wake up fc->waitq]
+ |                                    |      [sleep on req->waitq]
+
+If the filesystem daemon was single threaded, this will stop here,
+since there's no other thread to dequeue and execute the request.
+In this case the solution is to kill the FUSE daemon as well.  If
+there are multiple serving threads, you just have to kill them as
+long as any remain.
+
+Moral: a filesystem which deadlocks, can soon find itself dead.
+
+Scenario 2 - Tricky deadlock
+----------------------------
+
+This one needs a carefully crafted filesystem.  It's a variation on
+the above, only the call back to the filesystem is not explicit,
+but is caused by a pagefault.
+
+ |  Kamikaze filesystem thread 1      |  Kamikaze filesystem thread 2
+ |                                    |
+ |  [fd = open("/mnt/fuse/file")]     |  [request served normally]
+ |  [mmap fd to 'addr']               |
+ |  [close fd]                        |  [FLUSH triggers 'magic' flag]
+ |  [read a byte from addr]           |
+ |    >do_page_fault()                |
+ |      [find or create page]         |
+ |      [lock page]                   |
+ |      >fuse_readpage()              |
+ |         [queue READ request]       |
+ |         [sleep on req->waitq]      |
+ |                                    |  [read request to buffer]
+ |                                    |  [create reply header before addr]
+ |                                    |  >sys_write(addr - headerlength)
+ |                                    |    >fuse_dev_write()
+ |                                    |      [look up req in fc->processing]
+ |                                    |      [remove from fc->processing]
+ |                                    |      [copy write buffer to req]
+ |                                    |        >do_page_fault()
+ |                                    |           [find or create page]
+ |                                    |           [lock page]
+ |                                    |           * DEADLOCK *
+
+Solution is again to let the the request be interrupted (not
+elaborated further).
+
+An additional problem is that while the write buffer is being
+copied to the request, the request must not be interrupted.  This
+is because the destination address of the copy may not be valid
+after the request is interrupted.
+
+This is solved with doing the copy atomically, and allowing
+interruption while the page(s) belonging to the write buffer are
+faulted with get_user_pages().  The 'req->locked' flag indicates
+when the copy is taking place, and interruption is delayed until
+this flag is unset.
+
index 5024ba7a592c065820216ecf21ee862355170d41..d4773565ea2f20fabf868505f8b48f2ea7b6295a 100644 (file)
@@ -1241,16 +1241,38 @@ swap-intensive.
 overcommit_memory
 -----------------
 
-This file  contains  one  value.  The following algorithm is used to decide if
-there's enough  memory:  if  the  value of overcommit_memory is positive, then
-there's always  enough  memory. This is a useful feature, since programs often
-malloc() huge  amounts  of  memory 'just in case', while they only use a small
-part of  it.  Leaving  this value at 0 will lead to the failure of such a huge
-malloc(), when in fact the system has enough memory for the program to run.
-
-On the  other  hand,  enabling this feature can cause you to run out of memory
-and thrash the system to death, so large and/or important servers will want to
-set this value to 0.
+Controls overcommit of system memory, possibly allowing processes
+to allocate (but not use) more memory than is actually available.
+
+
+0      -       Heuristic overcommit handling. Obvious overcommits of
+               address space are refused. Used for a typical system. It
+               ensures a seriously wild allocation fails while allowing
+               overcommit to reduce swap usage.  root is allowed to
+               allocate slighly more memory in this mode. This is the
+               default.
+
+1      -       Always overcommit. Appropriate for some scientific
+               applications.
+
+2      -       Don't overcommit. The total address space commit
+               for the system is not permitted to exceed swap plus a
+               configurable percentage (default is 50) of physical RAM.
+               Depending on the percentage you use, in most situations
+               this means a process will not be killed while attempting
+               to use already-allocated memory but will receive errors
+               on memory allocation as appropriate.
+
+overcommit_ratio
+----------------
+
+Percentage of physical memory size to include in overcommit calculations
+(see above.)
+
+Memory allocation limit = swapspace + physmem * (overcommit_ratio / 100)
+
+       swapspace = total size of all swap areas
+       physmem = size of physical memory in system
 
 nr_hugepages and hugetlb_shm_group
 ----------------------------------
diff --git a/Documentation/filesystems/v9fs.txt b/Documentation/filesystems/v9fs.txt
new file mode 100644 (file)
index 0000000..4e92feb
--- /dev/null
@@ -0,0 +1,95 @@
+                       V9FS: 9P2000 for Linux
+                       ======================
+
+ABOUT
+=====
+
+v9fs is a Unix implementation of the Plan 9 9p remote filesystem protocol.
+
+This software was originally developed by Ron Minnich <rminnich@lanl.gov>
+and Maya Gokhale <maya@lanl.gov>.  Additional development by Greg Watson
+<gwatson@lanl.gov> and most recently Eric Van Hensbergen
+<ericvh@gmail.com> and Latchesar Ionkov <lucho@ionkov.net>.
+
+USAGE
+=====
+
+For remote file server:
+
+       mount -t 9P 10.10.1.2 /mnt/9
+
+For Plan 9 From User Space applications (http://swtch.com/plan9)
+
+       mount -t 9P `namespace`/acme /mnt/9 -o proto=unix,name=$USER
+
+OPTIONS
+=======
+
+  proto=name   select an alternative transport.  Valid options are
+               currently:
+                       unix - specifying a named pipe mount point
+                       tcp  - specifying a normal TCP/IP connection
+                       fd   - used passed file descriptors for connection
+                                (see rfdno and wfdno)
+
+  name=name    user name to attempt mount as on the remote server.  The
+               server may override or ignore this value.  Certain user
+               names may require authentication.
+
+  aname=name   aname specifies the file tree to access when the server is
+               offering several exported file systems.
+
+  debug=n      specifies debug level.  The debug level is a bitmask.
+                       0x01 = display verbose error messages
+                       0x02 = developer debug (DEBUG_CURRENT)
+                       0x04 = display 9P trace
+                       0x08 = display VFS trace
+                       0x10 = display Marshalling debug
+                       0x20 = display RPC debug
+                       0x40 = display transport debug
+                       0x80 = display allocation debug
+
+  rfdno=n      the file descriptor for reading with proto=fd
+
+  wfdno=n      the file descriptor for writing with proto=fd
+
+  maxdata=n    the number of bytes to use for 9P packet payload (msize)
+
+  port=n       port to connect to on the remote server
+
+  timeout=n    request timeouts (in ms) (default 60000ms)
+
+  noextend     force legacy mode (no 9P2000.u semantics)
+
+  uid          attempt to mount as a particular uid
+
+  gid          attempt to mount with a particular gid
+
+  afid         security channel - used by Plan 9 authentication protocols
+
+  nodevmap     do not map special files - represent them as normal files.
+               This can be used to share devices/named pipes/sockets between
+               hosts.  This functionality will be expanded in later versions.
+
+RESOURCES
+=========
+
+The Linux version of the 9P server, along with some client-side utilities
+can be found at http://v9fs.sf.net (along with a CVS repository of the
+development branch of this module).  There are user and developer mailing
+lists here, as well as a bug-tracker.
+
+For more information on the Plan 9 Operating System check out
+http://plan9.bell-labs.com/plan9
+
+For information on Plan 9 from User Space (Plan 9 applications and libraries
+ported to Linux/BSD/OSX/etc) check out http://swtch.com/plan9
+
+
+STATUS
+======
+
+The 2.6 kernel support is working on PPC and x86.
+
+PLEASE USE THE SOURCEFORGE BUG-TRACKER TO REPORT PROBLEMS.
+
index 3f318dd44c775fa21a5a407b85032e4683e03905..f042c12e0ed2d24683e1b83ddfd130b561ad0e1b 100644 (file)
@@ -1,35 +1,27 @@
-/* -*- auto-fill -*-                                                         */
 
-               Overview of the Virtual File System
+             Overview of the Linux Virtual File System
 
-               Richard Gooch <rgooch@atnf.csiro.au>
+       Original author: Richard Gooch <rgooch@atnf.csiro.au>
 
-                             5-JUL-1999
+                 Last updated on August 25, 2005
 
+  Copyright (C) 1999 Richard Gooch
+  Copyright (C) 2005 Pekka Enberg
 
-Conventions used in this document                                     <section>
-=================================
+  This file is released under the GPLv2.
 
-Each section in this document will have the string "<section>" at the
-right-hand side of the section title. Each subsection will have
-"<subsection>" at the right-hand side. These strings are meant to make
-it easier to search through the document.
 
-NOTE that the master copy of this document is available online at:
-http://www.atnf.csiro.au/~rgooch/linux/docs/vfs.txt
-
-
-What is it?                                                           <section>
+What is it?
 ===========
 
 The Virtual File System (otherwise known as the Virtual Filesystem
 Switch) is the software layer in the kernel that provides the
 filesystem interface to userspace programs. It also provides an
 abstraction within the kernel which allows different filesystem
-implementations to co-exist.
+implementations to coexist.
 
 
-A Quick Look At How It Works                                          <section>
+A Quick Look At How It Works
 ============================
 
 In this section I'll briefly describe how things work, before
@@ -38,7 +30,8 @@ when user programs open and manipulate files, and then look from the
 other view which is how a filesystem is supported and subsequently
 mounted.
 
-Opening a File                                                     <subsection>
+
+Opening a File
 --------------
 
 The VFS implements the open(2), stat(2), chmod(2) and similar system
@@ -77,7 +70,7 @@ back to userspace.
 
 Opening a file requires another operation: allocation of a file
 structure (this is the kernel-side implementation of file
-descriptors). The freshly allocated file structure is initialised with
+descriptors). The freshly allocated file structure is initialized with
 a pointer to the dentry and a set of file operation member functions.
 These are taken from the inode data. The open() file method is then
 called so the specific filesystem implementation can do it's work. You
@@ -102,7 +95,8 @@ filesystem or driver code at the same time, on different
 processors. You should ensure that access to shared resources is
 protected by appropriate locks.
 
-Registering and Mounting a Filesystem                              <subsection>
+
+Registering and Mounting a Filesystem
 -------------------------------------
 
 If you want to support a new kind of filesystem in the kernel, all you
@@ -123,17 +117,21 @@ updated to point to the root inode for the new filesystem.
 It's now time to look at things in more detail.
 
 
-struct file_system_type                                               <section>
+struct file_system_type
 =======================
 
-This describes the filesystem. As of kernel 2.1.99, the following
+This describes the filesystem. As of kernel 2.6.13, the following
 members are defined:
 
 struct file_system_type {
        const char *name;
        int fs_flags;
-       struct super_block *(*read_super) (struct super_block *, void *, int);
-       struct file_system_type * next;
+        struct super_block *(*get_sb) (struct file_system_type *, int,
+                                       const char *, void *);
+        void (*kill_sb) (struct super_block *);
+        struct module *owner;
+        struct file_system_type * next;
+        struct list_head fs_supers;
 };
 
   name: the name of the filesystem type, such as "ext2", "iso9660",
@@ -141,51 +139,97 @@ struct file_system_type {
 
   fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
 
-  read_super: the method to call when a new instance of this
+  get_sb: the method to call when a new instance of this
        filesystem should be mounted
 
-  next: for internal VFS use: you should initialise this to NULL
+  kill_sb: the method to call when an instance of this filesystem
+       should be unmounted
+
+  owner: for internal VFS use: you should initialize this to THIS_MODULE in
+       most cases.
 
-The read_super() method has the following arguments:
+  next: for internal VFS use: you should initialize this to NULL
+
+The get_sb() method has the following arguments:
 
   struct super_block *sb: the superblock structure. This is partially
-       initialised by the VFS and the rest must be initialised by the
-       read_super() method
+       initialized by the VFS and the rest must be initialized by the
+       get_sb() method
+
+  int flags: mount flags
+
+  const char *dev_name: the device name we are mounting.
 
   void *data: arbitrary mount options, usually comes as an ASCII
        string
 
   int silent: whether or not to be silent on error
 
-The read_super() method must determine if the block device specified
+The get_sb() method must determine if the block device specified
 in the superblock contains a filesystem of the type the method
 supports. On success the method returns the superblock pointer, on
 failure it returns NULL.
 
 The most interesting member of the superblock structure that the
-read_super() method fills in is the "s_op" field. This is a pointer to
+get_sb() method fills in is the "s_op" field. This is a pointer to
 a "struct super_operations" which describes the next level of the
 filesystem implementation.
 
+Usually, a filesystem uses generic one of the generic get_sb()
+implementations and provides a fill_super() method instead. The
+generic methods are:
+
+  get_sb_bdev: mount a filesystem residing on a block device
 
-struct super_operations                                               <section>
+  get_sb_nodev: mount a filesystem that is not backed by a device
+
+  get_sb_single: mount a filesystem which shares the instance between
+       all mounts
+
+A fill_super() method implementation has the following arguments:
+
+  struct super_block *sb: the superblock structure. The method fill_super()
+       must initialize this properly.
+
+  void *data: arbitrary mount options, usually comes as an ASCII
+       string
+
+  int silent: whether or not to be silent on error
+
+
+struct super_operations
 =======================
 
 This describes how the VFS can manipulate the superblock of your
-filesystem. As of kernel 2.1.99, the following members are defined:
+filesystem. As of kernel 2.6.13, the following members are defined:
 
 struct super_operations {
-       void (*read_inode) (struct inode *);
-       int (*write_inode) (struct inode *, int);
-       void (*put_inode) (struct inode *);
-       void (*drop_inode) (struct inode *);
-       void (*delete_inode) (struct inode *);
-       int (*notify_change) (struct dentry *, struct iattr *);
-       void (*put_super) (struct super_block *);
-       void (*write_super) (struct super_block *);
-       int (*statfs) (struct super_block *, struct statfs *, int);
-       int (*remount_fs) (struct super_block *, int *, char *);
-       void (*clear_inode) (struct inode *);
+        struct inode *(*alloc_inode)(struct super_block *sb);
+        void (*destroy_inode)(struct inode *);
+
+        void (*read_inode) (struct inode *);
+
+        void (*dirty_inode) (struct inode *);
+        int (*write_inode) (struct inode *, int);
+        void (*put_inode) (struct inode *);
+        void (*drop_inode) (struct inode *);
+        void (*delete_inode) (struct inode *);
+        void (*put_super) (struct super_block *);
+        void (*write_super) (struct super_block *);
+        int (*sync_fs)(struct super_block *sb, int wait);
+        void (*write_super_lockfs) (struct super_block *);
+        void (*unlockfs) (struct super_block *);
+        int (*statfs) (struct super_block *, struct kstatfs *);
+        int (*remount_fs) (struct super_block *, int *, char *);
+        void (*clear_inode) (struct inode *);
+        void (*umount_begin) (struct super_block *);
+
+        void (*sync_inodes) (struct super_block *sb,
+                                struct writeback_control *wbc);
+        int (*show_options)(struct seq_file *, struct vfsmount *);
+
+        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
 };
 
 All methods are called without any locks being held, unless otherwise
@@ -193,43 +237,62 @@ noted. This means that most methods can block safely. All methods are
 only called from a process context (i.e. not from an interrupt handler
 or bottom half).
 
+  alloc_inode: this method is called by inode_alloc() to allocate memory
+       for struct inode and initialize it.
+
+  destroy_inode: this method is called by destroy_inode() to release
+       resources allocated for struct inode.
+
   read_inode: this method is called to read a specific inode from the
-       mounted filesystem. The "i_ino" member in the "struct inode"
-       will be initialised by the VFS to indicate which inode to
-       read. Other members are filled in by this method
+        mounted filesystem.  The i_ino member in the struct inode is
+       initialized by the VFS to indicate which inode to read. Other
+       members are filled in by this method.
+
+       You can set this to NULL and use iget5_locked() instead of iget()
+       to read inodes.  This is necessary for filesystems for which the
+       inode number is not sufficient to identify an inode.
+
+  dirty_inode: this method is called by the VFS to mark an inode dirty.
 
   write_inode: this method is called when the VFS needs to write an
        inode to disc.  The second parameter indicates whether the write
        should be synchronous or not, not all filesystems check this flag.
 
   put_inode: called when the VFS inode is removed from the inode
-       cache. This method is optional
+       cache.
 
   drop_inode: called when the last access to the inode is dropped,
        with the inode_lock spinlock held.
 
-       This method should be either NULL (normal unix filesystem
+       This method should be either NULL (normal UNIX filesystem
        semantics) or "generic_delete_inode" (for filesystems that do not
        want to cache inodes - causing "delete_inode" to always be
        called regardless of the value of i_nlink)
 
-       The "generic_delete_inode()" behaviour is equivalent to the
+       The "generic_delete_inode()" behavior is equivalent to the
        old practice of using "force_delete" in the put_inode() case,
        but does not have the races that the "force_delete()" approach
        had. 
 
   delete_inode: called when the VFS wants to delete an inode
 
-  notify_change: called when VFS inode attributes are changed. If this
-       is NULL the VFS falls back to the write_inode() method. This
-       is called with the kernel lock held
-
   put_super: called when the VFS wishes to free the superblock
        (i.e. unmount). This is called with the superblock lock held
 
   write_super: called when the VFS superblock needs to be written to
        disc. This method is optional
 
+  sync_fs: called when VFS is writing out all dirty data associated with
+       a superblock. The second parameter indicates whether the method
+       should wait until the write out has been completed. Optional.
+
+  write_super_lockfs: called when VFS is locking a filesystem and forcing
+       it into a consistent state.  This function is currently used by the
+       Logical Volume Manager (LVM).
+
+  unlockfs: called when VFS is unlocking a filesystem and making it writable
+       again.
+
   statfs: called when the VFS needs to get filesystem statistics. This
        is called with the kernel lock held
 
@@ -238,21 +301,31 @@ or bottom half).
 
   clear_inode: called then the VFS clears the inode. Optional
 
+  umount_begin: called when the VFS is unmounting a filesystem.
+
+  sync_inodes: called when the VFS is writing out dirty data associated with
+       a superblock.
+
+  show_options: called by the VFS to show mount options for /proc/<pid>/mounts.
+
+  quota_read: called by the VFS to read from filesystem quota file.
+
+  quota_write: called by the VFS to write to filesystem quota file.
+
 The read_inode() method is responsible for filling in the "i_op"
 field. This is a pointer to a "struct inode_operations" which
 describes the methods that can be performed on individual inodes.
 
 
-struct inode_operations                                               <section>
+struct inode_operations
 =======================
 
 This describes how the VFS can manipulate an inode in your
-filesystem. As of kernel 2.1.99, the following members are defined:
+filesystem. As of kernel 2.6.13, the following members are defined:
 
 struct inode_operations {
-       struct file_operations * default_file_ops;
-       int (*create) (struct inode *,struct dentry *,int);
-       int (*lookup) (struct inode *,struct dentry *);
+       int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -261,25 +334,22 @@ struct inode_operations {
        int (*mknod) (struct inode *,struct dentry *,int,dev_t);
        int (*rename) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *);
-       int (*readlink) (struct dentry *, char *,int);
-       struct dentry * (*follow_link) (struct dentry *, struct dentry *);
-       int (*readpage) (struct file *, struct page *);
-       int (*writepage) (struct page *page, struct writeback_control *wbc);
-       int (*bmap) (struct inode *,int);
+       int (*readlink) (struct dentry *, char __user *,int);
+        void * (*follow_link) (struct dentry *, struct nameidata *);
+        void (*put_link) (struct dentry *, struct nameidata *, void *);
        void (*truncate) (struct inode *);
-       int (*permission) (struct inode *, int);
-       int (*smap) (struct inode *,int);
-       int (*updatepage) (struct file *, struct page *, const char *,
-                               unsigned long, unsigned int, int);
-       int (*revalidate) (struct dentry *);
+       int (*permission) (struct inode *, int, struct nameidata *);
+       int (*setattr) (struct dentry *, struct iattr *);
+       int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
+       int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
+       ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
+       ssize_t (*listxattr) (struct dentry *, char *, size_t);
+       int (*removexattr) (struct dentry *, const char *);
 };
 
 Again, all methods are called without any locks being held, unless
 otherwise noted.
 
-  default_file_ops: this is a pointer to a "struct file_operations"
-       which describes how to open and then manipulate open files
-
   create: called by the open(2) and creat(2) system calls. Only
        required if you want to support regular files. The dentry you
        get should not have an inode (i.e. it should be a negative
@@ -328,31 +398,143 @@ otherwise noted.
        you want to support reading symbolic links
 
   follow_link: called by the VFS to follow a symbolic link to the
-       inode it points to. Only required if you want to support
-       symbolic links
+       inode it points to.  Only required if you want to support
+       symbolic links.  This function returns a void pointer cookie
+       that is passed to put_link().
+
+  put_link: called by the VFS to release resources allocated by
+       follow_link().  The cookie returned by follow_link() is passed to
+       to this function as the last parameter.  It is used by filesystems
+       such as NFS where page cache is not stable (i.e. page that was
+       installed when the symbolic link walk started might not be in the
+       page cache at the end of the walk).
+
+  truncate: called by the VFS to change the size of a file.  The i_size
+       field of the inode is set to the desired size by the VFS before
+       this function is called.  This function is called by the truncate(2)
+       system call and related functionality.
+
+  permission: called by the VFS to check for access rights on a POSIX-like
+       filesystem.
+
+  setattr: called by the VFS to set attributes for a file.  This function is
+       called by chmod(2) and related system calls.
+
+  getattr: called by the VFS to get attributes of a file.  This function is
+       called by stat(2) and related system calls.
+
+  setxattr: called by the VFS to set an extended attribute for a file.
+       Extended attribute is a name:value pair associated with an inode. This
+       function is called by setxattr(2) system call.
+
+  getxattr: called by the VFS to retrieve the value of an extended attribute
+       name.  This function is called by getxattr(2) function call.
+
+  listxattr: called by the VFS to list all extended attributes for a given
+       file.  This function is called by listxattr(2) system call.
+
+  removexattr: called by the VFS to remove an extended attribute from a file.
+       This function is called by removexattr(2) system call.
+
+
+struct address_space_operations
+===============================
+
+This describes how the VFS can manipulate mapping of a file to page cache in
+your filesystem. As of kernel 2.6.13, the following members are defined:
+
+struct address_space_operations {
+       int (*writepage)(struct page *page, struct writeback_control *wbc);
+       int (*readpage)(struct file *, struct page *);
+       int (*sync_page)(struct page *);
+       int (*writepages)(struct address_space *, struct writeback_control *);
+       int (*set_page_dirty)(struct page *page);
+       int (*readpages)(struct file *filp, struct address_space *mapping,
+                       struct list_head *pages, unsigned nr_pages);
+       int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
+       int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
+       sector_t (*bmap)(struct address_space *, sector_t);
+       int (*invalidatepage) (struct page *, unsigned long);
+       int (*releasepage) (struct page *, int);
+       ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
+                       loff_t offset, unsigned long nr_segs);
+       struct page* (*get_xip_page)(struct address_space *, sector_t,
+                       int);
+};
+
+  writepage: called by the VM write a dirty page to backing store.
+
+  readpage: called by the VM to read a page from backing store.
+
+  sync_page: called by the VM to notify the backing store to perform all
+       queued I/O operations for a page. I/O operations for other pages
+       associated with this address_space object may also be performed.
+
+  writepages: called by the VM to write out pages associated with the
+       address_space object.
+
+  set_page_dirty: called by the VM to set a page dirty.
+
+  readpages: called by the VM to read pages associated with the address_space
+       object.
 
+  prepare_write: called by the generic write path in VM to set up a write
+       request for a page.
 
-struct file_operations                                                <section>
+  commit_write: called by the generic write path in VM to write page to
+       its backing store.
+
+  bmap: called by the VFS to map a logical block offset within object to
+       physical block number. This method is use by for the legacy FIBMAP
+       ioctl. Other uses are discouraged.
+
+  invalidatepage: called by the VM on truncate to disassociate a page from its
+       address_space mapping.
+
+  releasepage: called by the VFS to release filesystem specific metadata from
+       a page.
+
+  direct_IO: called by the VM for direct I/O writes and reads.
+
+  get_xip_page: called by the VM to translate a block number to a page.
+       The page is valid until the corresponding filesystem is unmounted.
+       Filesystems that want to use execute-in-place (XIP) need to implement
+       it.  An example implementation can be found in fs/ext2/xip.c.
+
+
+struct file_operations
 ======================
 
 This describes how the VFS can manipulate an open file. As of kernel
-2.1.99, the following members are defined:
+2.6.13, the following members are defined:
 
 struct file_operations {
        loff_t (*llseek) (struct file *, loff_t, int);
-       ssize_t (*read) (struct file *, char *, size_t, loff_t *);
-       ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
+       ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+       ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t);
+       ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+       ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
+       long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+       long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
        int (*open) (struct inode *, struct file *);
+       int (*flush) (struct file *);
        int (*release) (struct inode *, struct file *);
-       int (*fsync) (struct file *, struct dentry *);
-       int (*fasync) (struct file *, int);
-       int (*check_media_change) (kdev_t dev);
-       int (*revalidate) (kdev_t dev);
+       int (*fsync) (struct file *, struct dentry *, int datasync);
+       int (*aio_fsync) (struct kiocb *, int datasync);
+       int (*fasync) (int, struct file *, int);
        int (*lock) (struct file *, int, struct file_lock *);
+       ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
+       ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
+       ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
+       ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
+       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+       int (*check_flags)(int);
+       int (*dir_notify)(struct file *filp, unsigned long arg);
+       int (*flock) (struct file *, int, struct file_lock *);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -362,8 +544,12 @@ otherwise noted.
 
   read: called by read(2) and related system calls
 
+  aio_read: called by io_submit(2) and other asynchronous I/O operations
+
   write: called by write(2) and related system calls
 
+  aio_write: called by io_submit(2) and other asynchronous I/O operations
+
   readdir: called when the VFS needs to read the directory contents
 
   poll: called by the VFS when a process wants to check if there is
@@ -372,18 +558,25 @@ otherwise noted.
 
   ioctl: called by the ioctl(2) system call
 
+  unlocked_ioctl: called by the ioctl(2) system call. Filesystems that do not
+       require the BKL should use this method instead of the ioctl() above.
+
+  compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
+        are used on 64 bit kernels.
+
   mmap: called by the mmap(2) system call
 
   open: called by the VFS when an inode should be opened. When the VFS
-       opens a file, it creates a new "struct file" and initialises
-       the "f_op" file operations member with the "default_file_ops"
-       field in the inode structure. It then calls the open method
-       for the newly allocated file structure. You might think that
-       the open method really belongs in "struct inode_operations",
-       and you may be right. I think it's done the way it is because
-       it makes filesystems simpler to implement. The open() method
-       is a good place to initialise the "private_data" member in the
-       file structure if you want to point to a device structure
+       opens a file, it creates a new "struct file". It then calls the
+       open method for the newly allocated file structure. You might
+       think that the open method really belongs in
+       "struct inode_operations", and you may be right. I think it's
+       done the way it is because it makes filesystems simpler to
+       implement. The open() method is a good place to initialize the
+       "private_data" member in the file structure if you want to point
+       to a device structure
+
+  flush: called by the close(2) system call to flush a file
 
   release: called when the last reference to an open file is closed
 
@@ -392,6 +585,23 @@ otherwise noted.
   fasync: called by the fcntl(2) system call when asynchronous
        (non-blocking) mode is enabled for a file
 
+  lock: called by the fcntl(2) system call for F_GETLK, F_SETLK, and F_SETLKW
+       commands
+
+  readv: called by the readv(2) system call
+
+  writev: called by the writev(2) system call
+
+  sendfile: called by the sendfile(2) system call
+
+  get_unmapped_area: called by the mmap(2) system call
+
+  check_flags: called by the fcntl(2) system call for F_SETFL command
+
+  dir_notify: called by the fcntl(2) system call for F_NOTIFY command
+
+  flock: called by the flock(2) system call
+
 Note that the file operations are implemented by the specific
 filesystem in which the inode resides. When opening a device node
 (character or block special) most filesystems will call special
@@ -400,29 +610,28 @@ driver information. These support routines replace the filesystem file
 operations with those for the device driver, and then proceed to call
 the new open() method for the file. This is how opening a device file
 in the filesystem eventually ends up calling the device driver open()
-method. Note the devfs (the Device FileSystem) has a more direct path
-from device node to device driver (this is an unofficial kernel
-patch).
+method.
 
 
-Directory Entry Cache (dcache)                                        <section>
-------------------------------
+Directory Entry Cache (dcache)
+==============================
+
 
 struct dentry_operations
-========================
+------------------------
 
 This describes how a filesystem can overload the standard dentry
 operations. Dentries and the dcache are the domain of the VFS and the
 individual filesystem implementations. Device drivers have no business
 here. These methods may be set to NULL, as they are either optional or
-the VFS uses a default. As of kernel 2.1.99, the following members are
+the VFS uses a default. As of kernel 2.6.13, the following members are
 defined:
 
 struct dentry_operations {
-       int (*d_revalidate)(struct dentry *);
+       int (*d_revalidate)(struct dentry *, struct nameidata *);
        int (*d_hash) (struct dentry *, struct qstr *);
        int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
-       void (*d_delete)(struct dentry *);
+       int (*d_delete)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
 };
@@ -451,6 +660,7 @@ Each dentry has a pointer to its parent dentry, as well as a hash list
 of child dentries. Child dentries are basically like files in a
 directory.
 
+
 Directory Entry Cache APIs
 --------------------------
 
@@ -471,7 +681,7 @@ manipulate dentries:
        "d_delete" method is called
 
   d_drop: this unhashes a dentry from its parents hash list. A
-       subsequent call to dput() will dellocate the dentry if its
+       subsequent call to dput() will deallocate the dentry if its
        usage count drops to 0
 
   d_delete: delete a dentry. If there are no other open references to
@@ -507,16 +717,16 @@ up by walking the tree starting with the first component
 of the pathname and using that dentry along with the next
 component to look up the next level and so on. Since it
 is a frequent operation for workloads like multiuser
-environments and webservers, it is important to optimize
+environments and web servers, it is important to optimize
 this path.
 
 Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus
 in every component during path look-up. Since 2.5.10 onwards,
-fastwalk algorithm changed this by holding the dcache_lock
+fast-walk algorithm changed this by holding the dcache_lock
 at the beginning and walking as many cached path component
-dentries as possible. This signficantly decreases the number
+dentries as possible. This significantly decreases the number
 of acquisition of dcache_lock. However it also increases the
-lock hold time signficantly and affects performance in large
+lock hold time significantly and affects performance in large
 SMP machines. Since 2.5.62 kernel, dcache has been using
 a new locking model that uses RCU to make dcache look-up
 lock-free.
@@ -527,7 +737,7 @@ protected the hash chain, d_child, d_alias, d_lru lists as well
 as d_inode and several other things like mount look-up. RCU-based
 changes affect only the way the hash chain is protected. For everything
 else the dcache_lock must be taken for both traversing as well as
-updating. The hash chain updations too take the dcache_lock.
+updating. The hash chain updates too take the dcache_lock.
 The significant change is the way d_lookup traverses the hash chain,
 it doesn't acquire the dcache_lock for this and rely on RCU to
 ensure that the dentry has not been *freed*.
@@ -535,14 +745,15 @@ ensure that the dentry has not been *freed*.
 
 Dcache locking details
 ----------------------
+
 For many multi-user workloads, open() and stat() on files are
 very frequently occurring operations. Both involve walking
 of path names to find the dentry corresponding to the
 concerned file. In 2.4 kernel, dcache_lock was held
 during look-up of each path component. Contention and
-cacheline bouncing of this global lock caused significant
+cache-line bouncing of this global lock caused significant
 scalability problems. With the introduction of RCU
-in linux kernel, this was worked around by making
+in Linux kernel, this was worked around by making
 the look-up of path components during path walking lock-free.
 
 
@@ -562,7 +773,7 @@ Some of the important changes are :
 2. Insertion of a dentry into the hash table is done using
    hlist_add_head_rcu() which take care of ordering the writes -
    the writes to the dentry must be visible before the dentry
-   is inserted. This works in conjuction with hlist_for_each_rcu()
+   is inserted. This works in conjunction with hlist_for_each_rcu()
    while walking the hash chain. The only requirement is that
    all initialization to the dentry must be done before hlist_add_head_rcu()
    since we don't have dcache_lock protection while traversing
@@ -584,7 +795,7 @@ Some of the important changes are :
    the same.  In some sense, dcache_rcu path walking looks like
    the pre-2.5.10 version.
 
-5. All dentry hash chain updations must take the dcache_lock as well as
+5. All dentry hash chain updates must take the dcache_lock as well as
    the per-dentry lock in that order. dput() does this to ensure
    that a dentry that has just been looked up in another CPU
    doesn't get deleted before dget() can be done on it.
@@ -640,10 +851,10 @@ handled as described below :
    Since we redo the d_parent check and compare name while holding
    d_lock, lock-free look-up will not race against d_move().
 
-4. There can be a theoritical race when a dentry keeps coming back
+4. There can be a theoretical race when a dentry keeps coming back
    to original bucket due to double moves. Due to this look-up may
    consider that it has never moved and can end up in a infinite loop.
-   But this is not any worse that theoritical livelocks we already
+   But this is not any worse that theoretical livelocks we already
    have in the kernel.
 
 
index 4ccdcc6fe3645992a796eef7d6cfe763d1e232d2..8ec32cc49eb107bdab130a6cb24c54b6da9dfcb2 100644 (file)
@@ -878,7 +878,7 @@ DVD_READ_STRUCT                     Read structure
 
        error returns:
          EINVAL        physical.layer_num exceeds number of layers
-         EIO           Recieved invalid response from drive
+         EIO           Received invalid response from drive
 
 
 
index 9a1586590d827fcb11943247362c527dbe419105..d802ce88bedc923e5d5a6f49ec9bdc2deacb85bc 100644 (file)
@@ -31,7 +31,7 @@ This document describes the Linux kernel Makefiles.
 
        === 6 Architecture Makefiles
           --- 6.1 Set variables to tweak the build to the architecture
-          --- 6.2 Add prerequisites to prepare:
+          --- 6.2 Add prerequisites to archprepare:
           --- 6.3 List directories to visit when descending
           --- 6.4 Architecture specific boot images
           --- 6.5 Building non-kbuild targets
@@ -734,18 +734,18 @@ When kbuild executes the following steps are followed (roughly):
        for loadable kernel modules.
 
  
---- 6.2 Add prerequisites to prepare:
+--- 6.2 Add prerequisites to archprepare:
 
-       The prepare: rule is used to list prerequisites that needs to be
+       The archprepare: rule is used to list prerequisites that needs to be
        built before starting to descend down in the subdirectories.
        This is usual header files containing assembler constants.
 
                Example:
-               #arch/s390/Makefile
-               prepare: include/asm-$(ARCH)/offsets.h
+               #arch/arm/Makefile
+               archprepare: maketools
 
-       In this example the file include/asm-$(ARCH)/offsets.h will
-       be built before descending down in the subdirectories.
+       In this example the file target maketools will be processed
+       before descending down in the subdirectories.
        See also chapter XXX-TODO that describe how kbuild supports
        generating offset header files.
 
index 7ff213f4becd34d1f2a378c77f427aa3ac9c8033..1f5f7d28c9e6bf54e2b95d97f9399aed324b177f 100644 (file)
@@ -39,8 +39,7 @@ SETUP
    and apply http://lse.sourceforge.net/kdump/patches/kexec-tools-1.101-kdump.patch
    and after that build the source.
 
-2) Download and build the appropriate (latest) kexec/kdump (-mm) kernel
-   patchset and apply it to the vanilla kernel tree.
+2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernel.
 
    Two kernels need to be built in order to get this feature working.
 
@@ -84,15 +83,16 @@ SETUP
 
 4) Load the second kernel to be booted using:
 
-   kexec -p <second-kernel> --crash-dump --args-linux --append="root=<root-dev>
-   init 1 irqpoll"
+   kexec -p <second-kernel> --args-linux --elf32-core-headers
+   --append="root=<root-dev> init 1 irqpoll"
 
    Note: i) <second-kernel> has to be a vmlinux image. bzImage will not work,
            as of now.
-       ii) By default ELF headers are stored in ELF32 format (for i386). This
-           is sufficient to represent the physical memory up to 4GB. To store
-           headers in ELF64 format, specifiy "--elf64-core-headers" on the
-           kexec command line additionally.
+       ii) By default ELF headers are stored in ELF64 format. Option
+           --elf32-core-headers forces generation of ELF32 headers. gdb can
+           not open ELF64 headers on 32 bit systems. So creating ELF32
+           headers can come handy for users who have got non-PAE systems and
+           hence have memory less than 4GB.
        iii) Specify "irqpoll" as command line parameter. This reduces driver
             initialization failures in second kernel due to shared interrupts.
 
index d2f0c67ba1fb01e419966178138629048d2202bb..7086f0a90d14a47d6ba3295e624a7bda414062a9 100644 (file)
@@ -164,6 +164,15 @@ running once the system is up.
                        over-ride platform specific driver.
                        See also Documentation/acpi-hotkey.txt.
 
+       enable_timer_pin_1 [i386,x86-64]
+                       Enable PIN 1 of APIC timer
+                       Can be useful to work around chipset bugs (in particular on some ATI chipsets)
+                       The kernel tries to set a reasonable default.
+
+       disable_timer_pin_1 [i386,x86-64]
+                       Disable PIN 1 of APIC timer
+                       Can be useful to work around chipset bugs.
+
        ad1816=         [HW,OSS]
                        Format: <io>,<irq>,<dma>,<dma2>
                        See also Documentation/sound/oss/AD1816.
@@ -549,6 +558,7 @@ running once the system is up.
                             keyboard and can not control its state
                             (Don't attempt to blink the leds)
        i8042.noaux     [HW] Don't check for auxiliary (== mouse) port
+       i8042.nokbd     [HW] Don't check/create keyboard port
        i8042.nomux     [HW] Don't check presence of an active multiplexing
                             controller
        i8042.nopnp     [HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
index 6739ab9615ef7085441fae78c6f4695bd36d5682..807a0c7b4737c60fe8d119d54b65ebf4ba80af10 100644 (file)
@@ -30,7 +30,7 @@ other program after you have done the following:
    Read the file 'binfmt_misc.txt' in this directory to know
    more about the configuration process.
 
-3) Add the following enries to /etc/rc.local or similar script
+3) Add the following entries to /etc/rc.local or similar script
    to be run at system startup:
 
 # Insert BINFMT_MISC module into the kernel
index 24d029455baadabc3acc398e3970ff8052e3ab1d..a55f0f95b171a3bbe80b5e19c535a2707e957f64 100644 (file)
@@ -1241,7 +1241,7 @@ traffic while still maintaining carrier on.
 
        If running SNMP agents, the bonding driver should be loaded
 before any network drivers participating in a bond.  This requirement
-is due to the the interface index (ipAdEntIfIndex) being associated to
+is due to the interface index (ipAdEntIfIndex) being associated to
 the first interface found with a given IP address.  That is, there is
 only one ipAdEntIfIndex for each IP address.  For example, if eth0 and
 eth1 are slaves of bond0 and the driver for eth0 is loaded before the
@@ -1937,7 +1937,7 @@ switches currently available support 802.3ad.
        If not explicitly configured (with ifconfig or ip link), the
 MAC address of the bonding device is taken from its first slave
 device.  This MAC address is then passed to all following slaves and
-remains persistent (even if the the first slave is removed) until the
+remains persistent (even if the first slave is removed) until the
 bonding device is brought down or reconfigured.
 
        If you wish to change the MAC address, you can set it with
index aea20cd2a56e0f68071088b893a7e78d9dd1a5bb..c96897aa08b6b89f9845a131635b69842877a575 100644 (file)
@@ -355,7 +355,7 @@ REVISION HISTORY
                                There is no functional difference between the two packages         
 
 2.0.7   Aug 26, 1999           o  Merged X25API code into WANPIPE.
-                               o  Fixed a memeory leak for X25API
+                               o  Fixed a memory leak for X25API
                                o  Updated the X25API code for 2.2.X kernels.
                                o  Improved NEM handling.   
 
@@ -514,7 +514,7 @@ beta2-2.2.0 Jan 8 2001
                                o Patches for 2.4.0 kernel
                                o Patches for 2.2.18 kernel
                                o Minor updates to PPP and CHLDC drivers.
-                                 Note: No functinal difference. 
+                                 Note: No functional difference.
 
 beta3-2.2.9    Jan 10 2001
                                o I missed the 2.2.18 kernel patches in beta2-2.2.0
index 76d28d033657aac4158b8db93821553f332d6b11..711210b38f5fe4c1dfa84db9392cf0c5c75dfa49 100644 (file)
@@ -84,7 +84,7 @@ Each entry consists of:
 
 Most drivers don't need to use the driver_data field.  Best practice
 for use of driver_data is to use it as an index into a static list of
-equivalant device types, not to use it as a pointer.
+equivalent device types, not to use it as a pointer.
 
 Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}
 to have probe() called for every PCI device known to the system.
index 2bfe71beec5b1cacad0464298d8acebacc4c7f27..e75d7474322cd915b07c169c358617dc639caf31 100644 (file)
@@ -134,7 +134,7 @@ pci_get_device_by_addr() will find the pci device associated
 with that address (if any).
 
 The default include/asm-ppc64/io.h macros readb(), inb(), insb(),
-etc. include a check to see if the the i/o read returned all-0xff's.
+etc. include a check to see if the i/o read returned all-0xff's.
 If so, these make a call to eeh_dn_check_failure(), which in turn
 asks the firmware if the all-ff's value is the sign of a true EEH
 error.  If it is not, processing continues as normal.  The grand
index e24fdeada9705e3e9a14cc4195592e832d169c00..e321a8ed2a2d6bf78581673b967cc9fe45186435 100644 (file)
@@ -468,7 +468,7 @@ The hex_ascii view shows the data field in hex and ascii representation
 The raw view returns a bytestream as the debug areas are stored in memory.
 
 The sprintf view formats the debug entries in the same way as the sprintf
-function would do. The sprintf event/expection fuctions write to the 
+function would do. The sprintf event/expection functions write to the
 debug entry a pointer to the format string (size = sizeof(long)) 
 and for each vararg a long value. So e.g. for a debug entry with a format 
 string plus two varargs one would need to allocate a (3 * sizeof(long)) 
index 2814491600ff472c315d31ad60da806bcb3496a2..2ffb3ae0ef4d1d8fa7c27aa1ecb5238d4c8d9878 100644 (file)
    /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
    
    This table is quite informative for interested users. It shows the load
-   of commands on the subsystem and wether you are running the bypassed 
+   of commands on the subsystem and whether you are running the bypassed
    (software) or integrated (hardware) SCSI-command set (see below). The
    amount of accesses is shown. Read, write, modeselect is shown separately
    in order to help debugging problems with CD-ROMs or tapedrives.
index 5c49ba07e709625516952f4d1147f0ae61464a37..ebfcdf28485f28aa47ee6af8fd5f4f639aadda59 100644 (file)
@@ -1459,7 +1459,7 @@ devices where %i is sound card number from zero to seven.
 To auto-load an ALSA driver for OSS services, define the string
 'sound-slot-%i' where %i means the slot number for OSS, which
 corresponds to the card index of ALSA.  Usually, define this
-as the the same card module.
+as the same card module.
 
 An example configuration for a single emu10k1 card is like below:
 ----- /etc/modprobe.conf
index f97841478459037c5627814f345c30c3d3ed6d21..5df44dc894e594a7ef6344a05a0439fe7ebcce98 100644 (file)
@@ -57,7 +57,7 @@ With BK, you can just get it from
 
 and DaveJ has tar-balls at
 
-       http://www.codemonkey.org.uk/projects/bitkeeper/sparse/
+       http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
 
 
 Once you have it, just do
index 136d817c01babb51fc8e80ba5917544a7204c5ab..baf17b381588d0899512b0e65b29adda91aa49bc 100644 (file)
@@ -171,7 +171,7 @@ the header 'include/linux/sysrq.h', this will define everything else you need.
 Next, you must create a sysrq_key_op struct, and populate it with A) the key
 handler function you will use, B) a help_msg string, that will print when SysRQ
 prints help, and C) an action_msg string, that will print right before your
-handler is called. Your handler must conform to the protoype in 'sysrq.h'.
+handler is called. Your handler must conform to the prototype in 'sysrq.h'.
 
 After the sysrq_key_op is created, you can call the macro 
 register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
index 0c7b654fec996c388dd99af3dcc8a7884ca30989..544430e3998027f2c822ff4d27d9123e4d7f5c90 100644 (file)
   If you want to access files on the host machine from inside UML, you
   can treat it as a separate machine and either nfs mount directories
   from the host or copy files into the virtual machine with scp or rcp.
-  However, since UML is running on the the host, it can access those
+  However, since UML is running on the host, it can access those
   files just like any other process and make them available inside the
   virtual machine without needing to use the network.
 
index a938c3dd13d657fc504b84e58d4c5781a30c97fa..815f5c2301ffa8599ce35dd3d684bf66afbfcc02 100644 (file)
@@ -20,7 +20,7 @@ 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 document and the the gadget serial driver itself are
+This document and the gadget serial driver itself are
 Copyright (C) 2004 by Al Borchers (alborchers@steinerpoint.com).
 
 If you have questions, problems, or suggestions for this driver
index 62a12a08e2ac5c431ecb50e9358296a9ff76c0f3..ec785f9f15a3168e5d95f230b19da743e7a588db 100644 (file)
@@ -126,10 +126,12 @@ card=124 - AverMedia AverTV DVB-T 761
 card=125 - MATRIX Vision Sigma-SQ
 card=126 - MATRIX Vision Sigma-SLC
 card=127 - APAC Viewcomp 878(AMAX)
-card=128 - DVICO FusionHDTV DVB-T Lite
+card=128 - DViCO FusionHDTV DVB-T Lite
 card=129 - V-Gear MyVCD
 card=130 - Super TV Tuner
 card=131 - Tibet Systems 'Progress DVR' CS16
 card=132 - Kodicom 4400R (master)
 card=133 - Kodicom 4400R (slave)
 card=134 - Adlink RTV24
+card=135 - DViCO FusionHDTV 5 Lite
+card=136 - Acorp Y878F
index 1b5a3a9ffbe2bbf7913a934888e23c034260ff5c..dc57225f39be5b973f74fe0e7f2b451bdc1c7821 100644 (file)
@@ -62,3 +62,6 @@
  61 -> Philips TOUGH DVB-T reference design     [1131:2004]
  62 -> Compro VideoMate TV Gold+II
  63 -> Kworld Xpert TV PVR7134
+ 64 -> FlyTV mini Asus Digimatrix               [1043:0210,1043:0210]
+ 65 -> V-Stream Studio TV Terminator
+ 66 -> Yuan TUN-900 (saa7135)
index f3302e1b1b9c4a31836612917336af57094befcd..f5876be658a64f3724df1ef71cc41b5786f15a38 100644 (file)
@@ -64,3 +64,4 @@ tuner=62 - Philips TEA5767HN FM Radio
 tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
 tuner=64 - LG TDVS-H062F/TUA6034
 tuner=65 - Ymec TVF66T5-B/DFF
+tuner=66 - LG NTSC (TALN mini series)
index 01425c21986ba7ee03408f74537a36d2be7b2912..52c94bd7dca1f909cc16ddc2f40351cfbefad5ab 100644 (file)
@@ -222,7 +222,7 @@ was introduced in 1991, is used in the DC10 old
 can generate: PAL , NTSC , SECAM
 
 The adv717x, should be able to produce PAL N. But you find nothing PAL N 
-specific in the the registers. Seem that you have to reuse a other standard
+specific in the registers. Seem that you have to reuse a other standard
 to generate PAL N, maybe it would work if you use the PAL M settings. 
 
 ==========================
index 678e8f192db2917c741ca0b88ddc97f761a4a8d7..ffe1c062088b9daa52954b2dd6054975f52b9a7b 100644 (file)
@@ -11,6 +11,11 @@ Machine check
                If your BIOS doesn't do that it's a good idea to enable though
                to make sure you log even machine check events that result
                in a reboot.
+   mce=tolerancelevel (number)
+               0: always panic, 1: panic if deadlock possible,
+               2: try to avoid panic, 3: never panic or exit (for testing)
+               default is 1
+               Can be also set using sysfs which is preferable.
 
    nomce (for compatibility with i386): same as mce=off
 
diff --git a/Kbuild b/Kbuild
new file mode 100644 (file)
index 0000000..7900391
--- /dev/null
+++ b/Kbuild
@@ -0,0 +1,49 @@
+#
+# Kbuild for top-level directory of the kernel
+# This file takes care of the following:
+# 1) Generate asm-offsets.h
+
+#####
+# 1) Generate asm-offsets.h
+#
+
+offsets-file := include/asm-$(ARCH)/asm-offsets.h
+
+always  := $(offsets-file)
+targets := $(offsets-file)
+targets += arch/$(ARCH)/kernel/asm-offsets.s
+
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+       "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
+endef
+# Override default regexp for specific architectures
+sed-$(CONFIG_MIPS) := "/^@@@/s///p"
+
+quiet_cmd_offsets = GEN     $@
+define cmd_offsets
+       mkdir -p $(dir $@); \
+       cat $< | \
+       (set -e; \
+        echo "#ifndef __ASM_OFFSETS_H__"; \
+        echo "#define __ASM_OFFSETS_H__"; \
+        echo "/*"; \
+        echo " * DO NOT MODIFY."; \
+        echo " *"; \
+        echo " * This file was generated by $(srctree)/Kbuild"; \
+        echo " *"; \
+        echo " */"; \
+        echo ""; \
+        sed -ne $(sed-y); \
+        echo ""; \
+        echo "#endif" ) > $@
+endef
+
+# We use internal kbuild rules to avoid the "is up to date" message from make
+arch/$(ARCH)/kernel/asm-offsets.s: arch/$(ARCH)/kernel/asm-offsets.c FORCE
+       $(Q)mkdir -p $(dir $@)
+       $(call if_changed_dep,cc_s_c)
+
+$(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild
+       $(call cmd,offsets)
+
index 1dc2a6b0f642f01c81221f0d532375f46a9a526a..a67bf7d315d7ee14923789fc66eb08649178f4ce 100644 (file)
@@ -626,6 +626,12 @@ M: rmk@arm.linux.org.uk
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
 
+CYBLAFB FRAMEBUFFER DRIVER
+P:     Knut Petersen
+M:     Knut_Petersen@t-online.de
+L:     linux-fbdev-devel@lists.sourceforge.net
+S:     Maintained
+
 CYCLADES 2X SYNC CARD DRIVER
 P:     Arnaldo Carvalho de Melo
 M:     acme@conectiva.com.br
@@ -925,6 +931,13 @@ L: linux-tape@vger.kernel.org
 W:     http://sourceforge.net/projects/ftape
 S:     Orphan
 
+FUSE: FILESYSTEM IN USERSPACE
+P:     Miklos Szeredi
+M:     miklos@szeredi.hu
+L:     fuse-devel@lists.sourceforge.net
+W:     http://fuse.sourceforge.net/
+S:     Maintained
+
 FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
 P:     Rik Faith
 M:     faith@cs.unc.edu
@@ -2691,6 +2704,17 @@ L:       rio500-users@lists.sourceforge.net
 W:     http://rio500.sourceforge.net
 S:     Maintained
 
+V9FS FILE SYSTEM
+P:      Eric Van Hensbergen
+M:      ericvh@gmail.com
+P:      Ron Minnich
+M:      rminnich@lanl.gov
+P:      Latchesar Ionkov
+M:      lucho@ionkov.net
+L:      v9fs-developer@lists.sourceforge.net
+W:      http://v9fs.sf.net
+S:      Maintained
+
 VIDEO FOR LINUX
 P:     Mauro Carvalho Chehab
 M:     mchehab@brturbo.com.br
index 63e5c9f0bc7ad9776a4f9a33e07600b0085c5672..45e5a38fbc7aee34f68a852e4a6530609ccc52f2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -334,7 +334,7 @@ KALLSYMS    = scripts/kallsyms
 PERL           = perl
 CHECK          = sparse
 
-CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ $(CF)
 MODFLAGS       = -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -382,6 +382,9 @@ RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CV
 scripts_basic:
        $(Q)$(MAKE) $(build)=scripts/basic
 
+# To avoid any implicit rule to kick in, define an empty command.
+scripts/basic/%: scripts_basic ;
+
 .PHONY: outputmakefile
 # outputmakefile generate a Makefile to be placed in output directory, if
 # using a seperate output directory. This allows convinient use
@@ -444,9 +447,8 @@ ifeq ($(config-targets),1)
 include $(srctree)/arch/$(ARCH)/Makefile
 export KBUILD_DEFCONFIG
 
-config: scripts_basic outputmakefile FORCE
-       $(Q)$(MAKE) $(build)=scripts/kconfig $@
-%config: scripts_basic outputmakefile FORCE
+config %config: scripts_basic outputmakefile FORCE
+       $(Q)mkdir -p include/linux
        $(Q)$(MAKE) $(build)=scripts/kconfig $@
 
 else
@@ -489,6 +491,7 @@ include .config
 # If .config is newer than include/linux/autoconf.h, someone tinkered
 # with it and forgot to run make oldconfig
 include/linux/autoconf.h: .config
+       $(Q)mkdir -p include/linux
        $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
 # Dummy target needed, because used as prerequisite
@@ -641,8 +644,13 @@ quiet_cmd_vmlinux__ ?= LD      $@
 # Generate new vmlinux version
 quiet_cmd_vmlinux_version = GEN     .version
       cmd_vmlinux_version = set -e;                     \
-       . $(srctree)/scripts/mkversion > .tmp_version;  \
-       mv -f .tmp_version .version;                    \
+       if [ ! -r .version ]; then                      \
+         rm -f .version;                               \
+         echo 1 >.version;                             \
+       else                                            \
+         mv .version .old_version;                     \
+         expr 0$$(cat .old_version) + 1 >.version;     \
+       fi;                                             \
        $(MAKE) $(build)=init
 
 # Generate System.map
@@ -756,6 +764,7 @@ endif # ifdef CONFIG_KALLSYMS
 # vmlinux image - including updated kernel symbols
 vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
        $(call if_changed_rule,vmlinux__)
+       $(Q)rm -f .old_version
 
 # The actual objects are generated when descending, 
 # make sure no implicit rule kicks in
@@ -768,22 +777,27 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
 # Error messages still appears in the original language
 
 .PHONY: $(vmlinux-dirs)
-$(vmlinux-dirs): prepare-all scripts
+$(vmlinux-dirs): prepare scripts
        $(Q)$(MAKE) $(build)=$@
 
 # Things we need to do before we recursively start building the kernel
-# or the modules are listed in "prepare-all".
-# A multi level approach is used. prepare1 is updated first, then prepare0.
-# prepare-all is the collection point for the prepare targets.
+# or the modules are listed in "prepare".
+# A multi level approach is used. prepareN is processed before prepareN-1.
+# archprepare is used in arch Makefiles and when processed asm symlink,
+# version.h and scripts_basic is processed / created.
+
+# Listed in dependency order
+.PHONY: prepare archprepare prepare0 prepare1 prepare2 prepare3
 
-.PHONY: prepare-all prepare prepare0 prepare1 prepare2
+# prepare-all is deprecated, use prepare as valid replacement
+.PHONY: prepare-all
 
-# prepare2 is used to check if we are building in a separate output directory,
+# prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
 # 2) Create the include2 directory, used for the second asm symlink
 
-prepare2:
+prepare3:
 ifneq ($(KBUILD_SRC),)
        @echo '  Using $(srctree) as source for kernel'
        $(Q)if [ -f $(srctree)/.config ]; then \
@@ -795,18 +809,23 @@ ifneq ($(KBUILD_SRC),)
        $(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm
 endif
 
-# prepare1 creates a makefile if using a separate output directory
-prepare1: prepare2 outputmakefile
+# prepare2 creates a makefile if using a separate output directory
+prepare2: prepare3 outputmakefile
 
-prepare0: prepare1 include/linux/version.h include/asm \
+prepare1: prepare2 include/linux/version.h include/asm \
                    include/config/MARKER
 ifneq ($(KBUILD_MODULES),)
        $(Q)rm -rf $(MODVERDIR)
        $(Q)mkdir -p $(MODVERDIR)
 endif
 
+archprepare: prepare1 scripts_basic
+
+prepare0: archprepare FORCE
+       $(Q)$(MAKE) $(build)=.
+
 # All the preparing..
-prepare-all: prepare0 prepare
+prepare prepare-all: prepare0
 
 #      Leave this as default for preprocessing vmlinux.lds.S, which is now
 #      done in arch/$(ARCH)/kernel/Makefile
@@ -845,7 +864,7 @@ include/asm:
 
 #      Split autoconf.h into include/linux/config/*
 
-include/config/MARKER: include/linux/autoconf.h
+include/config/MARKER: scripts/basic/split-include include/linux/autoconf.h
        @echo '  SPLIT   include/linux/autoconf.h -> include/config/*'
        @scripts/basic/split-include include/linux/autoconf.h include/config
        @touch $@
@@ -897,7 +916,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
 
 # Target to prepare building external modules
 .PHONY: modules_prepare
-modules_prepare: prepare-all scripts
+modules_prepare: prepare scripts
 
 # Target to install modules
 .PHONY: modules_install
@@ -949,26 +968,6 @@ modules modules_install: FORCE
 
 endif # CONFIG_MODULES
 
-# Generate asm-offsets.h 
-# ---------------------------------------------------------------------------
-
-define filechk_gen-asm-offsets
-       (set -e; \
-        echo "#ifndef __ASM_OFFSETS_H__"; \
-        echo "#define __ASM_OFFSETS_H__"; \
-        echo "/*"; \
-        echo " * DO NOT MODIFY."; \
-        echo " *"; \
-        echo " * This file was generated by arch/$(ARCH)/Makefile"; \
-        echo " *"; \
-        echo " */"; \
-        echo ""; \
-        sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
-        echo ""; \
-        echo "#endif" )
-endef
-
-
 ###
 # Cleaning is done on three levels.
 # make clean     Delete most generated files
@@ -991,7 +990,7 @@ MRPROPER_FILES += .config .config.old include/asm .version \
 #
 clean: rm-dirs  := $(CLEAN_DIRS)
 clean: rm-files := $(CLEAN_FILES)
-clean-dirs      := $(addprefix _clean_,$(vmlinux-alldirs))
+clean-dirs      := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs))
 
 .PHONY: $(clean-dirs) clean archclean
 $(clean-dirs):
@@ -1070,6 +1069,7 @@ help:
        @echo  '  rpm             - Build a kernel as an RPM package'
        @echo  '  tags/TAGS       - Generate tags file for editors'
        @echo  '  cscope          - Generate cscope index'
+       @echo  '  kernelrelease   - Output the release version string'
        @echo  ''
        @echo  'Static analysers'
        @echo  '  buildcheck      - List dangling references to vmlinux discarded sections'
index 224c34741d32d139aec5d5ff110cfd5398565f58..f9da827a0c1880154757981e1430f01f071181f2 100644 (file)
@@ -9,7 +9,7 @@ screen please read "Documentation/oops-tracing.txt" before posting your
 bug report. This explains what you should do with the "Oops" information
 to make it useful to the recipient.
 
-      Send the output the maintainer of the kernel area that seems to
+      Send the output to the maintainer of the kernel area that seems to
 be involved with the problem. Don't worry too much about getting the
 wrong person. If you are unsure send it to the person responsible for the
 code relevant to what you were doing. If it occurs repeatably try and
@@ -18,15 +18,15 @@ The list of maintainers is in the MAINTAINERS file in this directory.
 
       If it is a security bug, please copy the Security Contact listed
 in the MAINTAINERS file.  They can help coordinate bugfix and disclosure.
-See Documentation/SecurityBugs for more infomation.
+See Documentation/SecurityBugs for more information.
 
       If you are totally stumped as to whom to send the report, send it to
 linux-kernel@vger.kernel.org. (For more information on the linux-kernel
 mailing list see http://www.tux.org/lkml/).
 
-This is a suggested format for a bug report sent to the Linux kernel mailing 
-list. Having a standardized bug report form makes it easier  for you not to 
-overlook things, and easier for the developers to find the pieces of 
+This is a suggested format for a bug report sent to the Linux kernel mailing
+list. Having a standardized bug report form makes it easier for you not to
+overlook things, and easier for the developers to find the pieces of
 information they're really interested in. Don't feel you have to follow it.
 
       First run the ver_linux script included as scripts/ver_linux, which
@@ -35,9 +35,9 @@ the command "sh scripts/ver_linux".
 
 Use that information to fill in all fields of the bug report form, and
 post it to the mailing list with a subject of "PROBLEM: <one line
-summary from [1.]>" for easy identification by the developers    
+summary from [1.]>" for easy identification by the developers.
 
-[1.] One line summary of the problem:    
+[1.] One line summary of the problem:
 [2.] Full description of the problem/report:
 [3.] Keywords (i.e., modules, networking, kernel):
 [4.] Kernel version (from /proc/version):
index 22ebfb2be0e4c655a5e764eb0c99598b4035cb37..1b704ee54bf3ad5210aab22c6f36d372aadc19e6 100644 (file)
@@ -108,20 +108,9 @@ $(boot)/vmlinux.gz: vmlinux
 bootimage bootpfile bootpzfile: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
-
-prepare: include/asm-$(ARCH)/asm_offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
-
 define archhelp
   echo '* boot         - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
   echo '  bootimage    - SRM bootable image (arch/alpha/boot/bootimage)'
index fc5ef90c4fc95863653860190f76dc92a647616a..24ae9a3660737767db4ca7f4b1a7da997703bd76 100644 (file)
@@ -185,15 +185,6 @@ EXPORT_SYMBOL(smp_num_cpus);
 EXPORT_SYMBOL(smp_call_function);
 EXPORT_SYMBOL(smp_call_function_on_cpu);
 EXPORT_SYMBOL(_atomic_dec_and_lock);
-#ifdef CONFIG_DEBUG_SPINLOCK
-EXPORT_SYMBOL(_raw_spin_unlock);
-EXPORT_SYMBOL(debug_spin_lock);
-EXPORT_SYMBOL(debug_spin_trylock);
-#endif
-#ifdef CONFIG_DEBUG_RWLOCK
-EXPORT_SYMBOL(_raw_write_lock);
-EXPORT_SYMBOL(_raw_read_lock);
-#endif
 EXPORT_SYMBOL(cpu_present_mask);
 #endif /* CONFIG_SMP */
 
index f0927ee53f29c73b5491e692117e5dec2ee88d97..76cc0cb5fc2e429ebe0a98026271bbff7a6225f9 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/pal.h>
 #include <asm/errno.h>
index 4ca2e404708a46cd8bc4681a57ce1c9f2db7f964..0905721fcbcaba4f89425b8d22d0281426e78b81 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/config.h>
 #include <asm/system.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
 .globl swapper_pg_dir
 .globl _stext
index fc271e316a388f774150777f8f35f955484d8151..aac6d4b22f7a23dd81a2f954fb380778708a0cf9 100644 (file)
@@ -47,7 +47,7 @@ module_free(struct module *mod, void *module_region)
 
 struct got_entry {
        struct got_entry *next;
-       Elf64_Addr r_offset;
+       Elf64_Sxword r_addend;
        int got_offset;
 };
 
@@ -57,14 +57,14 @@ process_reloc_for_got(Elf64_Rela *rela,
 {
        unsigned long r_sym = ELF64_R_SYM (rela->r_info);
        unsigned long r_type = ELF64_R_TYPE (rela->r_info);
-       Elf64_Addr r_offset = rela->r_offset;
+       Elf64_Sxword r_addend = rela->r_addend;
        struct got_entry *g;
 
        if (r_type != R_ALPHA_LITERAL)
                return;
 
        for (g = chains + r_sym; g ; g = g->next)
-               if (g->r_offset == r_offset) {
+               if (g->r_addend == r_addend) {
                        if (g->got_offset == 0) {
                                g->got_offset = *poffset;
                                *poffset += 8;
@@ -74,7 +74,7 @@ process_reloc_for_got(Elf64_Rela *rela,
 
        g = kmalloc (sizeof (*g), GFP_KERNEL);
        g->next = chains[r_sym].next;
-       g->r_offset = r_offset;
+       g->r_addend = r_addend;
        g->got_offset = *poffset;
        *poffset += 8;
        chains[r_sym].next = g;
index 167fd89f8707aeb1b0ad59190e9fa352718d5900..0636116210d236e2ed0353c4296036e2edf793ec 100644 (file)
@@ -974,6 +974,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
        size_t size;
        long timeout;
        int ret = -EINVAL;
+       struct fdtable *fdt;
 
        timeout = MAX_SCHEDULE_TIMEOUT;
        if (tvp) {
@@ -995,7 +996,8 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
                }
        }
 
-       if (n < 0 || n > current->files->max_fdset)
+       fdt = files_fdtable(current->files);
+       if (n < 0 || n > fdt->max_fdset)
                goto out_nofds;
 
        /*
@@ -1152,8 +1154,7 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
 
        ticks = timeval_to_jiffies(&tmp);
 
-       current->state = TASK_INTERRUPTIBLE;
-       ticks = schedule_timeout(ticks);
+       ticks = schedule_timeout_interruptible(ticks);
 
        if (remain) {
                jiffies_to_timeval(ticks, &tmp);
index e211aa7404e6152c4668277fdc03872547d8fab1..da0be34657915beec4cab3beeb15af6d33e0956c 100644 (file)
@@ -989,175 +989,3 @@ flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 
        preempt_enable();
 }
-\f
-#ifdef CONFIG_DEBUG_SPINLOCK
-void
-_raw_spin_unlock(spinlock_t * lock)
-{
-       mb();
-       lock->lock = 0;
-
-       lock->on_cpu = -1;
-       lock->previous = NULL;
-       lock->task = NULL;
-       lock->base_file = "none";
-       lock->line_no = 0;
-}
-
-void
-debug_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
-{
-       long tmp;
-       long stuck;
-       void *inline_pc = __builtin_return_address(0);
-       unsigned long started = jiffies;
-       int printed = 0;
-       int cpu = smp_processor_id();
-
-       stuck = 1L << 30;
- try_again:
-
-       /* Use sub-sections to put the actual loop at the end
-          of this object file's text section so as to perfect
-          branch prediction.  */
-       __asm__ __volatile__(
-       "1:     ldl_l   %0,%1\n"
-       "       subq    %2,1,%2\n"
-       "       blbs    %0,2f\n"
-       "       or      %0,1,%0\n"
-       "       stl_c   %0,%1\n"
-       "       beq     %0,3f\n"
-       "4:     mb\n"
-       ".subsection 2\n"
-       "2:     ldl     %0,%1\n"
-       "       subq    %2,1,%2\n"
-       "3:     blt     %2,4b\n"
-       "       blbs    %0,2b\n"
-       "       br      1b\n"
-       ".previous"
-       : "=r" (tmp), "=m" (lock->lock), "=r" (stuck)
-       : "m" (lock->lock), "2" (stuck) : "memory");
-
-       if (stuck < 0) {
-               printk(KERN_WARNING
-                      "%s:%d spinlock stuck in %s at %p(%d)"
-                      " owner %s at %p(%d) %s:%d\n",
-                      base_file, line_no,
-                      current->comm, inline_pc, cpu,
-                      lock->task->comm, lock->previous,
-                      lock->on_cpu, lock->base_file, lock->line_no);
-               stuck = 1L << 36;
-               printed = 1;
-               goto try_again;
-       }
-
-       /* Exiting.  Got the lock.  */
-       lock->on_cpu = cpu;
-       lock->previous = inline_pc;
-       lock->task = current;
-       lock->base_file = base_file;
-       lock->line_no = line_no;
-
-       if (printed) {
-               printk(KERN_WARNING
-                      "%s:%d spinlock grabbed in %s at %p(%d) %ld ticks\n",
-                      base_file, line_no, current->comm, inline_pc,
-                      cpu, jiffies - started);
-       }
-}
-
-int
-debug_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
-{
-       int ret;
-       if ((ret = !test_and_set_bit(0, lock))) {
-               lock->on_cpu = smp_processor_id();
-               lock->previous = __builtin_return_address(0);
-               lock->task = current;
-       } else {
-               lock->base_file = base_file;
-               lock->line_no = line_no;
-       }
-       return ret;
-}
-#endif /* CONFIG_DEBUG_SPINLOCK */
-\f
-#ifdef CONFIG_DEBUG_RWLOCK
-void _raw_write_lock(rwlock_t * lock)
-{
-       long regx, regy;
-       int stuck_lock, stuck_reader;
-       void *inline_pc = __builtin_return_address(0);
-
- try_again:
-
-       stuck_lock = 1<<30;
-       stuck_reader = 1<<30;
-
-       __asm__ __volatile__(
-       "1:     ldl_l   %1,%0\n"
-       "       blbs    %1,6f\n"
-       "       blt     %1,8f\n"
-       "       mov     1,%1\n"
-       "       stl_c   %1,%0\n"
-       "       beq     %1,6f\n"
-       "4:     mb\n"
-       ".subsection 2\n"
-       "6:     blt     %3,4b   # debug\n"
-       "       subl    %3,1,%3 # debug\n"
-       "       ldl     %1,%0\n"
-       "       blbs    %1,6b\n"
-       "8:     blt     %4,4b   # debug\n"
-       "       subl    %4,1,%4 # debug\n"
-       "       ldl     %1,%0\n"
-       "       blt     %1,8b\n"
-       "       br      1b\n"
-       ".previous"
-       : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (regy),
-         "=&r" (stuck_lock), "=&r" (stuck_reader)
-       : "m" (*(volatile int *)lock), "3" (stuck_lock), "4" (stuck_reader) : "memory");
-
-       if (stuck_lock < 0) {
-               printk(KERN_WARNING "write_lock stuck at %p\n", inline_pc);
-               goto try_again;
-       }
-       if (stuck_reader < 0) {
-               printk(KERN_WARNING "write_lock stuck on readers at %p\n",
-                      inline_pc);
-               goto try_again;
-       }
-}
-
-void _raw_read_lock(rwlock_t * lock)
-{
-       long regx;
-       int stuck_lock;
-       void *inline_pc = __builtin_return_address(0);
-
- try_again:
-
-       stuck_lock = 1<<30;
-
-       __asm__ __volatile__(
-       "1:     ldl_l   %1,%0;"
-       "       blbs    %1,6f;"
-       "       subl    %1,2,%1;"
-       "       stl_c   %1,%0;"
-       "       beq     %1,6f;"
-       "4:     mb\n"
-       ".subsection 2\n"
-       "6:     ldl     %1,%0;"
-       "       blt     %2,4b   # debug\n"
-       "       subl    %2,1,%2 # debug\n"
-       "       blbs    %1,6b;"
-       "       br      1b\n"
-       ".previous"
-       : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (stuck_lock)
-       : "m" (*(volatile int *)lock), "2" (stuck_lock) : "memory");
-
-       if (stuck_lock < 0) {
-               printk(KERN_WARNING "read_lock stuck at %p\n", inline_pc);
-               goto try_again;
-       }
-}
-#endif /* CONFIG_DEBUG_RWLOCK */
index cc5ce3a5fcad2dc10d918e60f749ea1127dcd58d..3c1f3e6522e5d59aa9c2b290b7095b02c90108f5 100644 (file)
@@ -5,7 +5,7 @@
  * Verify that we have not overflowed the stack.  Oops if we have.
  */
 
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
        .set noat
index e09f2ae1e09e36b8639c241141d5fa93df060464..e9f6a9dcf2b7c31bc947127422bf0fd7d9462072 100644 (file)
@@ -6,7 +6,7 @@
  * uninitialized local variables in the act.
  */
 
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
        .set noat
index 0f2899b4159dfb4f12c4cc2d69f411dd9d88e0af..11fff042aa817d022139947e82093d24a3e567a4 100644 (file)
@@ -326,8 +326,8 @@ config SMP
          processor machines. On a single processor machine, the kernel will
          run faster if you say N here.
 
-         See also the <file:Documentation/smp.tex>,
-         <file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
+         See also the <file:Documentation/smp.txt>,
+         <file:Documentation/i386/IO-APIC.txt>,
          <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
          <http://www.linuxdoc.org/docs.html#howto>.
 
index 45a5709eaaa459ef876ef6e406013f94880b395e..5d3acff8c596e0c0670d7d956379d860e9591ba7 100644 (file)
@@ -53,7 +53,7 @@ config DEBUG_LL
        bool "Kernel low-level debugging functions"
        depends on DEBUG_KERNEL
        help
-         Say Y here to include definitions of printascii, printchar, printhex
+         Say Y here to include definitions of printascii, printch, printhex
          in the kernel.  This is helpful if you are debugging code that
          executes before the console is initialized.
 
index 67f1453ade05e9afc085a7b0fb93e518dd053af8..130e6228b58713465c5fe4ef0061bb878b0cb4c2 100644 (file)
@@ -175,10 +175,10 @@ else
 endif
        @touch $@
 
-prepare: maketools include/asm-arm/.arch
+archprepare: maketools include/asm-arm/.arch
 
 .PHONY: maketools FORCE
-maketools: include/asm-arm/constants.h include/linux/version.h FORCE
+maketools: include/linux/version.h FORCE
        $(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
 
 # Convert bzImage to zImage
@@ -190,7 +190,7 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
-CLEAN_FILES += include/asm-arm/constants.h* include/asm-arm/mach-types.h \
+CLEAN_FILES += include/asm-arm/mach-types.h \
               include/asm-arm/arch include/asm-arm/.arch
 
 # We use MRPROPER_FILES and CLEAN_FILES now
@@ -201,11 +201,6 @@ archclean:
 bp:;   $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/bootpImage
 i zi:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/asm-arm/.arch
-
-include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
 
 define archhelp
   echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
index 688a595598c8a5cdc7b42a9b55a2b5ffe1868a17..d3a04c2a2c857192c7d861549acdfa320e78f681 100644 (file)
@@ -91,7 +91,7 @@ EXPORT_SYMBOL(read_scoop_reg);
 EXPORT_SYMBOL(write_scoop_reg);
 
 #ifdef CONFIG_PM
-static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
+static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
 {
        if (level == SUSPEND_POWER_DOWN) {
                struct scoop_dev *sdev = dev_get_drvdata(dev);
index db07ce42b3b2c6873f9b767389ae766d0f89ad6f..949ec4427f2165efdd2a7c04a66d391a76c7da6e 100644 (file)
@@ -10,7 +10,7 @@
  *  This file is included twice in entry-common.S
  */
 #ifndef NR_syscalls
-#define NR_syscalls 320
+#define NR_syscalls 328
 #else
 
 __syscall_start:
@@ -333,6 +333,9 @@ __syscall_start:
                .long   sys_inotify_init
                .long   sys_inotify_add_watch
                .long   sys_inotify_rm_watch
+               .long   sys_mbind_wrapper
+/* 320 */      .long   sys_get_mempolicy
+               .long   sys_set_mempolicy
 __syscall_end:
 
                .rept   NR_syscalls - (__syscall_end - __syscall_start) / 4
index 6281d488ac975d225aa10f536b5849db1b528956..db302c6e53439ddd553d42992109deccc3105741 100644 (file)
@@ -269,6 +269,10 @@ sys_arm_fadvise64_64_wrapper:
                str     r5, [sp, #4]            @ push r5 to stack
                b       sys_arm_fadvise64_64
 
+sys_mbind_wrapper:
+               str     r5, [sp, #4]
+               b       sys_mbind
+
 /*
  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
  * offset, we return EINVAL.
index afef21273963a6599fde7330e555f52f302faf60..648cfff93138bdc1df9e025efef31dbc1211a821 100644 (file)
@@ -3,7 +3,7 @@
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/errno.h>
 #include <asm/thread_info.h>
 
index 1155cf07c8710e7be4b55d92f144ffcdaeb5d10f..53962635134862263fb2719b3293249dc53187cc 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/mach-types.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
index 8f74e24536ba7b394c0b3b4786903e8839fb36b3..24c7b0477a09612ac65af3bc614812f5b4b7b276 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/linkage.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
 #define MMX_WR0                        (0x00)
 #define MMX_WR1                        (0x08)
index 4c38abdbe497b57d4cc460a9a55055d9df394b8b..68117968482bbe5f4c021732ba00624ee321ec54 100644 (file)
@@ -11,7 +11,7 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
 #define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
 
index 46a2dc962e9dd6f6420d120da6cfa988d1aecc21..333bca292de93a5b0eec17405207089395dbf88f 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
                .text
 
index 64aa6f4fe5e4a4dc3c888efb3a27e9a4275b0285..d204018070a49bde08c2c32b610c8b9edef37b5b 100644 (file)
@@ -26,7 +26,7 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000.
  * Note also that it is intended that __get_user_bad is not global.
  */
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/errno.h>
 
index b09398d95aac7cef468202ce0745597e7b505f7e..4593e9c07f0530b051559afa179189020247bf89 100644 (file)
@@ -26,7 +26,7 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000
  * Note also that it is intended that __put_user_bad is not global.
  */
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/errno.h>
 
index 29185acdd9e1ea7e6eb7a8f9182e18bac37f35b1..07b5dd453565402d9ec8c69b691681bae063be5a 100644 (file)
@@ -131,27 +131,12 @@ static struct platform_device corgits_device = {
 /*
  * MMC/SD Device
  *
- * The card detect interrupt isn't debounced so we delay it by HZ/4
+ * The card detect interrupt isn't debounced so we delay it by 250ms
  * to give the card a chance to fully insert/eject.
  */
-static struct mmc_detect {
-       struct timer_list detect_timer;
-       void *devid;
-} mmc_detect;
+static struct pxamci_platform_data corgi_mci_platform_data;
 
-static void mmc_detect_callback(unsigned long data)
-{
-       mmc_detect_change(mmc_detect.devid);
-}
-
-static irqreturn_t corgi_mmc_detect_int(int irq, void *devid, struct pt_regs *regs)
-{
-       mmc_detect.devid=devid;
-       mod_timer(&mmc_detect.detect_timer, jiffies + HZ/4);
-       return IRQ_HANDLED;
-}
-
-static int corgi_mci_init(struct device *dev, irqreturn_t (*unused_detect_int)(int, void *, struct pt_regs *), void *data)
+static int corgi_mci_init(struct device *dev, irqreturn_t (*corgi_detect_int)(int, void *, struct pt_regs *), void *data)
 {
        int err;
 
@@ -161,11 +146,9 @@ static int corgi_mci_init(struct device *dev, irqreturn_t (*unused_detect_int)(i
        pxa_gpio_mode(CORGI_GPIO_nSD_DETECT | GPIO_IN);
        pxa_gpio_mode(CORGI_GPIO_SD_PWR | GPIO_OUT);
 
-       init_timer(&mmc_detect.detect_timer);
-       mmc_detect.detect_timer.function = mmc_detect_callback;
-       mmc_detect.detect_timer.data = (unsigned long) &mmc_detect;
+       corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250);
 
-       err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_mmc_detect_int, SA_INTERRUPT,
+       err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, SA_INTERRUPT,
                             "MMC card detect", data);
        if (err) {
                printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
@@ -198,7 +181,6 @@ static int corgi_mci_get_ro(struct device *dev)
 static void corgi_mci_exit(struct device *dev, void *data)
 {
        free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data);
-       del_timer(&mmc_detect.detect_timer);
 }
 
 static struct pxamci_platform_data corgi_mci_platform_data = {
index 8ccffba0018fa5f1ef5d607c0be447ffc1dacd4c..366a9bde3d8be08880231795926d834839d35ddc 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/arch/corgi.h>
 #include <asm/arch/pxa-regs.h>
 
-static spinlock_t corgi_ssp_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(corgi_ssp_lock);
 static struct ssp_dev corgi_ssp_dev;
 static struct ssp_state corgi_ssp_state;
 
index 4664bd11adc1eb45931431ea38d895c819936b8a..0077937a7ab865f67faaca5ff684d2ca3cc0db6f 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
-
+#include <asm/arch/fb.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -103,6 +103,15 @@ struct platform_device s3c_device_lcd = {
 
 EXPORT_SYMBOL(s3c_device_lcd);
 
+static struct s3c2410fb_mach_info s3c2410fb_info;
+
+void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info)
+{
+       memcpy(&s3c2410fb_info,hard_s3c2410fb_info,sizeof(struct s3c2410fb_mach_info));
+       s3c_device_lcd.dev.platform_data = &s3c2410fb_info;
+}
+EXPORT_SYMBOL(set_s3c2410fb_info);
+
 /* NAND Controller */
 
 static struct resource s3c_nand_resource[] = {
index ea4fb1a97a50aa1fbcba1d883918808eb601d218..6ff1889fbd21facb8b13b3bcf1a9eff3685509fe 100644 (file)
@@ -45,6 +45,9 @@
 
 //#include <asm/debug-ll.h>
 #include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/fb.h>
 
 #include <linux/serial_core.h>
 
@@ -88,6 +91,48 @@ static struct s3c2410_uartcfg h1940_uartcfgs[] = {
 
 
 
+/**
+ * Set lcd on or off
+ **/
+static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
+       .fixed_syncs=           1,
+       .regs={
+               .lcdcon1=       S3C2410_LCDCON1_TFT16BPP | \
+                               S3C2410_LCDCON1_TFT | \
+                               S3C2410_LCDCON1_CLKVAL(0x0C),
+
+               .lcdcon2=       S3C2410_LCDCON2_VBPD(7) | \
+                               S3C2410_LCDCON2_LINEVAL(319) | \
+                               S3C2410_LCDCON2_VFPD(6) | \
+                               S3C2410_LCDCON2_VSPW(0),
+
+               .lcdcon3=       S3C2410_LCDCON3_HBPD(19) | \
+                               S3C2410_LCDCON3_HOZVAL(239) | \
+                               S3C2410_LCDCON3_HFPD(7),
+
+               .lcdcon4=       S3C2410_LCDCON4_MVAL(0) | \
+                               S3C2410_LCDCON4_HSPW(3),
+
+               .lcdcon5=       S3C2410_LCDCON5_FRM565 | \
+                               S3C2410_LCDCON5_INVVLINE | \
+                               S3C2410_LCDCON5_HWSWP,
+       },
+       .lpcsel=        0x02,
+       .gpccon=        0xaa940659,
+       .gpccon_mask=   0xffffffff,
+       .gpcup=         0x0000ffff,
+       .gpcup_mask=    0xffffffff,
+       .gpdcon=        0xaa84aaa0,
+       .gpdcon_mask=   0xffffffff,
+       .gpdup=         0x0000faff,
+       .gpdup_mask=    0xffffffff,
+
+       .width=         240,
+       .height=        320,
+       .xres=          {240,240,240},
+       .yres=          {320,320,320},
+       .bpp=           {16,16,16},
+};
 
 static struct platform_device *h1940_devices[] __initdata = {
        &s3c_device_usb,
@@ -116,6 +161,11 @@ void __init h1940_init_irq(void)
 
 }
 
+void __init h1940_init(void)
+{
+       set_s3c2410fb_info(&h1940_lcdcfg);
+}
+
 MACHINE_START(H1940, "IPAQ-H1940")
        /* Maintainer: Ben Dooks <ben@fluff.org> */
        .phys_ram       = S3C2410_SDRAM_PA,
@@ -124,5 +174,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
        .boot_params    = S3C2410_SDRAM_PA + 0x100,
        .map_io         = h1940_map_io,
        .init_irq       = h1940_init_irq,
+       .init_machine   = h1940_init,
        .timer          = &s3c24xx_timer,
 MACHINE_END
index 4940f1908316a0612fee9ce777a0b1299af92b60..3c58ebbf0359c0813ad5d0ac382d3fc6ba6f23fe 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
                .text
                .align  5
index b94c345ceb940f6956d4fafbd5cb0c0e3fbbf426..83117354b1cde16d2959b0cbc1166b2da6249b9a 100644 (file)
@@ -11,7 +11,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
        .text
        .align  5
index 976793937a937823ede2cb2e02823d1e623b01bd..e1f2af28d549ee9c7d9d3c2b1c5694132a9a695f 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
        .text
        .align  5
index 5c0ae5260d1cabef383c37d2dbe9cbc4da70f470..1d739d282a453ac9e1f266e3b05eaa6df2f479af 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
index d69389c4d4ba5410f9e13323313270bc01e14183..9b725665b5c77dad5ef9de56300974704d5e78d6 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
index 747ed963e1dfd6f2ead7eec9e83189fcb73a3e34..37b70fa21c767b671edc717a64f6e60f1567585a 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
index 248110c9cf139cc21b2e8498d4e168dce2aeed8d..931b690d1be24979bc17561d54506e09071c5c1e 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
index 189ef6a71ba102b49b66b2414a96d470332e3f46..d0f1bbb48f6c2cb9fc9e04c46dccf0bc377f94e5 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
index 57cfa6a2f54fdd229bd11b8113325d373743c4f3..c69c9de32391742f037d556046a4d0026f5ad949 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
index 9137fe563599a1e7f17280c6ec383eef274e5626..7cfc2604a1ee9b29211babfa3bc8348e16d7d7a0 100644 (file)
@@ -4,7 +4,7 @@
  *  VMA_VM_FLAGS
  *  VM_EXEC
  */
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
 /*
index 360cae905692bbc0ca6a6f6c3c219321b994bdbb..34f7e7d3f419c78c0aea1555cb6768fa51b6f566 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
index d447cd5f3dd9b3c80f6a4047c2bbe708e7a23840..ca14f80d5ab4b5b874bea29bef0be1359ceecdab 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/procinfo.h>
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
index 139a38670c5d07d35d37150adcd6358f64aefb22..eb34823c9dbf6f37a4f522e128c89db02f23f3b5 100644 (file)
@@ -11,7 +11,7 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/procinfo.h>
 #include <asm/pgtable.h>
 
index 44b0daeaff9bdde53b4b424de15de6f2ea4f94f2..c10786ec8e0a41b1036d4403bd4e3db94a1a108c 100644 (file)
@@ -13,7 +13,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
 
index db82ee46824857f8ee112017c9a0036bf88881a9..d6c94457c2b9d7b0949d97c02406e806038b5303 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
 
index 7908d5f1f1304d1275a927e608d96247698736c4..cb829ca7845d0d48293b4ff8c2eb71c4e751ddc3 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
 
index efbe94bbe1a74e4bd654115397e338173ae5282e..60cfc4a25dd5bff8e75855739ea6af3d1297e517 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
 
index 99ed26e78adfeea16853ef93b7adb5a90bf984dc..6f76b89ef46eab52fa7dbcaa483003ba28dd6527 100644 (file)
@@ -11,7 +11,7 @@
  *  These assume a split I/D TLB.
  */
 #include <linux/linkage.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/tlbflush.h>
 #include "proc-macros.S"
index 0ed38b0913dbb236002e1bfa8bfdb73fd049b832..51940a96d6a6bb74bb885add92157fdf0f98c984 100644 (file)
@@ -20,7 +20,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 
 /* This is the kernel's entry point into the floating point emulator.
 It is called from the kernel with code similar to this:
index e73c8deca592c68d25b9bbae2f89403c17a79407..6f17187ab32aa00b0fa65ede9a5c2a00a524c651 100644 (file)
@@ -17,7 +17,7 @@
  */
 #include <linux/linkage.h>
 #include <linux/init.h>
-#include <asm/constants.h>
+#include <asm/asm-offsets.h>
 #include <asm/vfpmacros.h>
 
        .globl  do_vfp
index e9cb8ef4f3fbdf0ae44197e9db145d506f28226a..844a9e46886e531584ff70c7a3c62a708fd3769a 100644 (file)
@@ -49,10 +49,6 @@ all: zImage
 
 boot := arch/arm26/boot
 
-prepare: include/asm-$(ARCH)/asm_offsets.h
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
-
-
 .PHONY: maketools FORCE
 maketools: FORCE
        
@@ -94,12 +90,6 @@ zi:; $(Q)$(MAKE) $(build)=$(boot) zinstall
        fi; \
        )
 
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
 define archhelp
   echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
index a231dd88d0e13fb514eeb92b53edf106840d10d6..6d910ea43d34dbc78b67be83e78822f9c3b34204 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/errno.h>
 #include <asm/hardware.h>
 #include <asm/sysirq.h>
index 2d79ee12ea1f736391f5e6fdd4a56d8f901ee883..c7511a2739d3f705471d1d9bc16cfb324d870fc8 100644 (file)
@@ -11,7 +11,7 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
                .text
                .align  5
index 5b821188e4792934a00a9be6903c379097f9b2cf..261dd154c1a46aed180a54c551708c6d2e0198aa 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
                .text
 
index e6d59b334851cee7c579bfbd7d1ca06e9df1fcea..2b1de7fbfe1fd29216006f7e7b34a7c8f53c6f0f 100644 (file)
@@ -26,7 +26,7 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000.
  * Note also that it is intended that __get_user_bad is not global.
  */
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/errno.h>
 
index 87588cbe46aecbd183f2e37b9ebd2506ebd32f94..46c7f15f9f2d9f54acc40a044ab7e8d888c914b9 100644 (file)
@@ -26,7 +26,7 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000
  * Note also that it is intended that __put_user_bad is not global.
  */
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/errno.h>
 
index c3d4cd3f457eab0d3e73a36cde3ee6c5da88c384..f9fca524c57afa920431d5cd20a41959928fd21e 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
 
index 7d6dfaad80c2122addd06b508879ce729c09224f..e6312000d9f8e90c14dfd75049a8aab7bc2c1c46 100644 (file)
@@ -20,7 +20,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
 /* This is the kernel's entry point into the floating point emulator.
 It is called from the kernel with code similar to this:
index 90ca8730b1203a1c33859d36cbf9dd48ad80e72e..ea65d585cf5ece14111068da24094a3ebeea9c1a 100644 (file)
@@ -107,8 +107,7 @@ archclean:
        rm -f timage vmlinux.bin decompress.bin rescue.bin cramfs.img
        rm -rf $(LD_SCRIPT).tmp
 
-prepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch \
-        include/asm-$(ARCH)/$(SARCH)/offset.h
+archprepare: $(SRC_ARCH)/.links $(srctree)/include/asm-$(ARCH)/.arch
 
 # Create some links to make all tools happy
 $(SRC_ARCH)/.links:
@@ -120,6 +119,7 @@ $(SRC_ARCH)/.links:
        @ln -sfn $(SRC_ARCH)/$(SARCH)/lib $(SRC_ARCH)/lib
        @ln -sfn $(SRC_ARCH)/$(SARCH) $(SRC_ARCH)/arch
        @ln -sfn $(SRC_ARCH)/$(SARCH)/vmlinux.lds.S $(SRC_ARCH)/kernel/vmlinux.lds.S
+       @ln -sfn $(SRC_ARCH)/$(SARCH)/asm-offsets.c $(SRC_ARCH)/kernel/asm-offsets.c
        @touch $@
 
 # Create link to sub arch includes
@@ -128,9 +128,3 @@ $(srctree)/include/asm-$(ARCH)/.arch: $(wildcard include/config/arch/*.h)
        @rm -f include/asm-$(ARCH)/arch
        @ln -sf $(srctree)/include/asm-$(ARCH)/$(SARCH) $(srctree)/include/asm-$(ARCH)/arch
        @touch $@
-
-arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                       include/config/MARKER
-
-include/asm-$(ARCH)/$(SARCH)/offset.h: arch/$(ARCH)/$(SARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
index c0163bf94a5001a3fe123d315e87ab83bc629a3d..c808005e8457862e144a2e34b8be90d25c5a5410 100644 (file)
 #include <asm/arch/sv_addr_ag.h>
 #include <asm/errno.h>
 #include <asm/thread_info.h>
-#include <asm/arch/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
index a8ed55e5b4031c09b93601db60c323ccfe1c9a24..3bd8503fec6842420ed7cf01d105fcd7b9f87e97 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/thread_info.h>
-#include <asm/arch/offset.h>
+#include <asm/asm-offsets.h>
 
 #include <asm/arch/hwregs/asm/reg_map_asm.h>
 #include <asm/arch/hwregs/asm/intr_vect_defs_asm.h>
diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..9e26311
--- /dev/null
@@ -0,0 +1 @@
+/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
index c9b80cffd71d5309c79747518de03190682a04a2..40b3f56f3666b2504b79c575a3e6c41ee0d09310 100644 (file)
@@ -61,12 +61,6 @@ archmrproper:
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-prepare: include/asm-$(ARCH)/asm-offsets.h
-
-include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
-                                  include/asm include/linux/version.h
-       $(call filechk,gen-asm-offsets)
-
 vmlinux.srec vmlinux.bin: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
@@ -74,5 +68,3 @@ define archhelp
   echo  'vmlinux.bin  - Create raw binary'
   echo  'vmlinux.srec - Create srec binary'
 endef
-
-CLEAN_FILES += include/asm-$(ARCH)/asm-offsets.h
index bf7c9ba709f32d97f8ae5d0a1e73638252f21979..09951990a6226b0a422c5812c6af7dbe67ef18a1 100644 (file)
@@ -156,15 +156,6 @@ install: vmlinux
 install kernel_install:
        $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
 
-prepare: include/asm-$(ARCH)/asm_offsets.h
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
 archclean:
        $(Q)$(MAKE) $(clean)=arch/i386/boot
 
index 0587477c99f2f32afa73a4dc10cf48e4ecb757d7..92f6694701420a1ef102f9155d2c1e1c349c91f5 100644 (file)
@@ -97,6 +97,7 @@
 #define PARAM_VESAPM_OFF       0x30
 #define PARAM_LFB_PAGES                0x32
 #define PARAM_VESA_ATTRIB      0x34
+#define PARAM_CAPABILITIES      0x36
 
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
@@ -233,6 +234,10 @@ mopar_gr:
        movw    18(%di), %ax
        movl    %eax, %fs:(PARAM_LFB_SIZE)
 
+# store mode capabilities
+       movl    10(%di), %eax
+       movl    %eax, %fs:(PARAM_CAPABILITIES)
+
 # switching the DAC to 8-bit is for <= 8 bpp only
        movw    %fs:(PARAM_LFB_DEPTH), %ax
        cmpw    $8, %ax
@@ -1944,7 +1949,7 @@ store_edid:
        movw    $0x4f15, %ax                    # do VBE/DDC
        movw    $0x01, %bx
        movw    $0x00, %cx
-       movw    $0x01, %dx
+       movw    $0x00, %dx
        movw    $0x140, %di
        int     $0x10
 
index f1b9d2a46dab860c0cbf100e1bf6b9b0b220c024..087ecc67e9b358e265e79ee450995e1ed73b6c46 100644 (file)
@@ -15,6 +15,13 @@ static int __init check_bridge(int vendor, int device)
        if (vendor == PCI_VENDOR_ID_NVIDIA) {
                acpi_skip_timer_override = 1;
        }
+       /*
+        * ATI IXP chipsets get double timer interrupts.
+        * For now just do this for all ATI chipsets.
+        * FIXME: this needs to be checked for the non ACPI case too.
+        */
+       if (vendor == PCI_VENDOR_ID_ATI)
+               disable_timer_pin_1 = 1;
        return 0;
 }
 
index 44d886c745ecc26063d88fed02a6d4929461337f..7c74fe0dc93c17b8a8bbb3483d0da623589d2449 100644 (file)
@@ -304,12 +304,6 @@ ret_point:
        call    restore_processor_state
        ret
 
-ENTRY(do_suspend_lowlevel_s4bios)
-       call save_processor_state
-       call save_registers
-       call acpi_enter_sleep_state_s4bios
-       ret
-
 ALIGN
 # saved registers
 saved_gdt:     .long   0,0
index 46ce9b248f5510088ca7fd1765fcfdd86ea44bd9..9ad43be9a01f0ebc2102f7d1fef5a11aa0146c71 100644 (file)
@@ -151,7 +151,7 @@ static char __devinit *table_lookup_model(struct cpuinfo_x86 *c)
 }
 
 
-void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+static void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
 {
        char *v = c->x86_vendor_id;
        int i;
index 3aad03839660de38dd8c24361ecbd6814de5eb52..9e24f7b207ee1636eabcafc48f6f630b56ed8d3e 100644 (file)
@@ -319,7 +319,7 @@ work_notifysig:                             # deal with pending signals and
                                        # vm86-space
        xorl %edx, %edx
        call do_notify_resume
-       jmp restore_all
+       jmp resume_userspace
 
        ALIGN
 work_notifysig_v86:
@@ -329,7 +329,7 @@ work_notifysig_v86:
        movl %eax, %esp
        xorl %edx, %edx
        call do_notify_resume
-       jmp restore_all
+       jmp resume_userspace
 
        # perform syscall exit tracing
        ALIGN
index 0480ca9e9e577a989d96e71e012b8b6e4f8e0c1d..e437fb367498c029ea21f5a7d5495d6b965a70cd 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/desc.h>
 #include <asm/cache.h>
 #include <asm/thread_info.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/setup.h>
 
 /*
index 1efdc76ae96dfcb4c4a9a0b4c89d843dd7398eeb..378313b0cce9ac9ba8de933303e5e432959cfa05 100644 (file)
@@ -60,6 +60,8 @@ int sis_apic_bug = -1;
  */
 int nr_ioapic_registers[MAX_IO_APICS];
 
+int disable_timer_pin_1 __initdata;
+
 /*
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
@@ -573,8 +575,7 @@ static int balanced_irq(void *unused)
        }
 
        for ( ; ; ) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               time_remaining = schedule_timeout(time_remaining);
+               time_remaining = schedule_timeout_interruptible(time_remaining);
                try_to_freeze();
                if (time_after(jiffies,
                                prev_balance_time+balanced_irq_interval)) {
@@ -2212,6 +2213,8 @@ static inline void check_timer(void)
                                setup_nmi();
                                enable_8259A_irq(0);
                        }
+                       if (disable_timer_pin_1 > 0)
+                               clear_IO_APIC_pin(0, pin1);
                        return;
                }
                clear_IO_APIC_pin(0, pin1);
index cafaeffe381857bd19de265957f9782496063f48..15949fd081095c76a44b217fdb5fad7384174146 100644 (file)
@@ -122,8 +122,8 @@ static int MP_valid_apicid(int apicid, int version)
 
 static void __init MP_processor_info (struct mpc_config_processor *m)
 {
-       int ver, apicid, cpu, found_bsp = 0;
-       physid_mask_t tmp;
+       int ver, apicid;
+       physid_mask_t phys_cpu;
        
        if (!(m->mpc_cpuflag & CPU_ENABLED))
                return;
@@ -181,7 +181,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
        if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
                Dprintk("    Bootup CPU\n");
                boot_cpu_physical_apicid = m->mpc_apicid;
-               found_bsp = 1;
        }
 
        if (num_processors >= NR_CPUS) {
@@ -195,29 +194,26 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
                        " Processor ignored.\n", maxcpus); 
                return;
        }
-       num_processors++;
        ver = m->mpc_apicver;
 
        if (!MP_valid_apicid(apicid, ver)) {
                printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
                        m->mpc_apicid, MAX_APICS);
-               --num_processors;
                return;
        }
 
-       if (found_bsp)
-               cpu = 0;
-       else
-               cpu = num_processors - 1;
-       cpu_set(cpu, cpu_possible_map);
-       tmp = apicid_to_cpu_present(apicid);
-       physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
-       
+       cpu_set(num_processors, cpu_possible_map);
+       num_processors++;
+       phys_cpu = apicid_to_cpu_present(apicid);
+       physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu);
+
        /*
         * Validate version
         */
        if (ver == 0x0) {
-               printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
+               printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! "
+                               "fixing up to 0x10. (tell your hw vendor)\n",
+                               m->mpc_apicid);
                ver = 0x10;
        }
        apic_version[m->mpc_apicid] = ver;
index 340980203b095f9cda5113c14369799815dad1e5..7b6368bf89746eaffc913d0c73e8b50d34ef15c4 100644 (file)
@@ -694,17 +694,22 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
 __attribute__((regparm(3)))
 int do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
-       int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU), ret = 0;
-       /* With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP for syscall
-        * interception. */
+       int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU);
+       /*
+        * With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP for syscall
+        * interception
+        */
        int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
+       int ret = 0;
 
        /* do the secure computing check first */
-       secure_computing(regs->orig_eax);
+       if (!entryexit)
+               secure_computing(regs->orig_eax);
 
        if (unlikely(current->audit_context)) {
                if (entryexit)
-                       audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
+                       audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
+                                               regs->eax);
                /* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
                 * on the syscall exit path. Normally, when TIF_SYSCALL_AUDIT is
                 * not used, entry.S will call us only on syscall exit, not
@@ -738,7 +743,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
        /* Note that the debugger could change the result of test_thread_flag!*/
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80:0));
 
        /*
         * this isn't the same as continuing with a signal, but it will do
@@ -750,7 +755,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
                current->exit_code = 0;
        }
        ret = is_sysemu;
- out:
+out:
        if (unlikely(current->audit_context) && !entryexit)
                audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
                                    regs->ebx, regs->ecx, regs->edx, regs->esi);
@@ -759,6 +764,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
 
        regs->orig_eax = -1; /* force skip of syscall restarting */
        if (unlikely(current->audit_context))
-               audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
+               audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
+                               regs->eax);
        return 1;
 }
index a659d274914cf26ccbc7431900d6423a391f66b1..dc39ca6a7eca82f546c649cb6b2e1b3c6a20b4a2 100644 (file)
@@ -139,6 +139,7 @@ struct sys_desc_table_struct {
        unsigned char table[0];
 };
 struct edid_info edid_info;
+EXPORT_SYMBOL_GPL(edid_info);
 struct ist_info ist_info;
 #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
        defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
@@ -850,6 +851,11 @@ static void __init parse_cmdline_early (char ** cmdline_p)
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC
+               if (!memcmp(from, "disable_timer_pin_1", 19))
+                       disable_timer_pin_1 = 1;
+               if (!memcmp(from, "enable_timer_pin_1", 18))
+                       disable_timer_pin_1 = -1;
+
                /* disable IO-APIC */
                else if (!memcmp(from, "noapic", 6))
                        disable_ioapic_setup();
@@ -1299,7 +1305,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
  */
 static void __init register_memory(void)
 {
-       unsigned long gapstart, gapsize;
+       unsigned long gapstart, gapsize, round;
        unsigned long long last;
        int           i;
 
@@ -1344,14 +1350,14 @@ static void __init register_memory(void)
        }
 
        /*
-        * Start allocating dynamic PCI memory a bit into the gap,
-        * aligned up to the nearest megabyte.
-        *
-        * Question: should we try to pad it up a bit (do something
-        * like " + (gapsize >> 3)" in there too?). We now have the
-        * technology.
+        * See how much we want to round up: start off with
+        * rounding to the next 1MB area.
         */
-       pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+       round = 0x100000;
+       while ((gapsize >> 4) > round)
+               round += round;
+       /* Fun with two's complement */
+       pci_mem_start = (gapstart + round) & -round;
 
        printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n",
                pci_mem_start, gapstart, gapsize);
index 5e4893d2b9f272b4c1120f3812cebef501f4164f..c70cd2a083045ea7ff12069a1fce5e9444cd6257 100644 (file)
@@ -1330,8 +1330,7 @@ void __cpu_die(unsigned int cpu)
                        printk ("CPU %d is now offline\n", cpu);
                        return;
                }
-               current->state = TASK_UNINTERRUPTIBLE;
-               schedule_timeout(HZ/10);
+               msleep(100);
        }
        printk(KERN_ERR "CPU %u didn't die...\n", cpu);
 }
index 7b3b27d64409381a9a557a58b6543feade5e6b9f..516bf5653b0266ea1f4beb9258bd6577c0b3e6ab 100644 (file)
@@ -213,12 +213,18 @@ static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_c
                node_end_pfn[nid] = memory_chunk->end_pfn;
 }
 
+static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
+
+int pxm_to_node(int pxm)
+{
+       return pxm_to_nid_map[pxm];
+}
+
 /* Parse the ACPI Static Resource Affinity Table */
 static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
        u8 *start, *end, *p;
        int i, j, nid;
-       u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
        u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
 
        start = (u8 *)(&(sratp->reserved) + 1); /* skip header */
index eefea7c5500893bd47e9d9485f7111ae34cd76e1..2883a4d4f01f824bfdc48457b82f3c0212b2690c 100644 (file)
@@ -329,8 +329,7 @@ EXPORT_SYMBOL(get_cmos_time);
 
 static void sync_cmos_clock(unsigned long dummy);
 
-static struct timer_list sync_cmos_timer =
-                                      TIMER_INITIALIZER(sync_cmos_clock, 0, 0);
+static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
 
 static void sync_cmos_clock(unsigned long dummy)
 {
index 13b9c62cbbb45ce1d95357a1784afea6f8e3db89..4710195b6b748e6cc69534f0f268e957a38edf58 100644 (file)
@@ -144,12 +144,7 @@ SECTIONS
        *(.exitcall.exit)
        }
 
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
+  STABS_DEBUG
+
+  DWARF_DEBUG
 }
index 68afa50dd7cf79bf0d5eb021115c59e03fee692f..fadb5bc3c37431cfda60e19d7f4e477e0126958a 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <asm/unistd.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
 
 /* XXX
index a7977707c8e5098455b56ed9c9463c124ad6e883..98699ca6e52d7b2febba30a086741a4f663da426 100644 (file)
@@ -3,7 +3,7 @@
  * object prelinked to its virtual address, and with only one read-only
  * segment (that fits in one page).  This script controls its layout.
  */
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
 SECTIONS
 {
index 42913f43feb0edca0015a1f2013c609cc361d802..2941674f35eb5aae272a3000edd491993ec1b0aa 100644 (file)
@@ -3,16 +3,31 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/hw_irq.h>
+#include <asm/numa.h>
 #include "pci.h"
 
 struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
 {
+       struct pci_bus *bus;
+
        if (domain != 0) {
                printk(KERN_WARNING "PCI: Multiple domains not supported\n");
                return NULL;
        }
 
-       return pcibios_scan_root(busnum);
+       bus = pcibios_scan_root(busnum);
+#ifdef CONFIG_ACPI_NUMA
+       if (bus != NULL) {
+               int pxm = acpi_get_pxm(device->handle);
+               if (pxm >= 0) {
+                       bus->sysdata = (void *)(unsigned long)pxm_to_node(pxm);
+                       printk("bus %d -> pxm %d -> node %ld\n",
+                               busnum, pxm, (long)(bus->sysdata));
+               }
+       }
+#endif
+       
+       return bus;
 }
 
 extern int pci_routeirq;
index 60f0e7a1162aafa3be94b2806384106dc1aee172..dfbf80cff8346af0504df3601e6e251becc7de06 100644 (file)
@@ -127,13 +127,6 @@ static int __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                goto out;
 
-       /* Kludge for now. Don't use mmconfig on AMD systems because
-          those have some busses where mmconfig doesn't work,
-          and we don't parse ACPI MCFG well enough to handle that. 
-          Remove when proper handling is added. */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-               goto out; 
-
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
index c4105286ff26fc4a8df8a1339c970b99d7e308a8..c893b897217fa597ce6c43692eb5630f171a1e25 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
 
index f9bd88ada708b3d9954f75ea4324b1ca2dd1b95d..70f8ed2748d1b41cc3f2ea1b9d44290ecd693c25 100644 (file)
@@ -82,25 +82,18 @@ unwcheck: vmlinux
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-CLEAN_FILES += include/asm-ia64/.offsets.h.stamp vmlinux.gz bootloader
-
-MRPROPER_FILES += include/asm-ia64/offsets.h
-
-prepare: include/asm-ia64/offsets.h
-
-arch/ia64/kernel/asm-offsets.s: include/asm include/linux/version.h include/config/MARKER
-
-include/asm-ia64/offsets.h: arch/ia64/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
-arch/ia64/kernel/asm-offsets.s: include/asm-ia64/.offsets.h.stamp
+archprepare:  include/asm-ia64/.offsets.h.stamp
 
 include/asm-ia64/.offsets.h.stamp:
        mkdir -p include/asm-ia64
-       [ -s include/asm-ia64/offsets.h ] \
-        || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/offsets.h
+       [ -s include/asm-ia64/asm-offsets.h ] \
+       || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/asm-offsets.h
        touch $@
 
+
+
+CLEAN_FILES += vmlinux.gz bootloader include/asm-ia64/.offsets.h.stamp
+
 boot:  lib/lib.a vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $@
 
index 1c8c7e6a9a5ecaba963c20ba69d2e93c76c0994a..a9bd71ac78e2dec37dc23695ae552953f283bd9d 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <asm/asmmacro.h>
+#include <asm/pal.h>
 
        .bss
        .align 16
@@ -49,7 +50,11 @@ GLOBAL_ENTRY(jmp_to_kernel)
        br.sptk.few b7
 END(jmp_to_kernel)
 
-
+/*
+ * r28 contains the index of the PAL function
+ * r29--31 the args
+ * Return values in ret0--3 (r8--11)
+ */
 GLOBAL_ENTRY(pal_emulator_static)
        mov r8=-1
        mov r9=256
@@ -62,7 +67,7 @@ GLOBAL_ENTRY(pal_emulator_static)
        cmp.gtu p6,p7=r9,r28
 (p6)   br.cond.sptk.few stacked
        ;;
-static:        cmp.eq p6,p7=6,r28              /* PAL_PTCE_INFO */
+static:        cmp.eq p6,p7=PAL_PTCE_INFO,r28
 (p7)   br.cond.sptk.few 1f
        ;;
        mov r8=0                        /* status = 0 */
@@ -70,21 +75,21 @@ static:     cmp.eq p6,p7=6,r28              /* PAL_PTCE_INFO */
        movl r10=0x0000000200000003     /* count[0], count[1] */
        movl r11=0x1000000000002000     /* stride[0], stride[1] */
        br.cond.sptk.few rp
-1:     cmp.eq p6,p7=14,r28             /* PAL_FREQ_RATIOS */
+1:     cmp.eq p6,p7=PAL_FREQ_RATIOS,r28
 (p7)   br.cond.sptk.few 1f
        mov r8=0                        /* status = 0 */
        movl r9 =0x100000064            /* proc_ratio (1/100) */
        movl r10=0x100000100            /* bus_ratio<<32 (1/256) */
        movl r11=0x100000064            /* itc_ratio<<32 (1/100) */
        ;;
-1:     cmp.eq p6,p7=19,r28             /* PAL_RSE_INFO */
+1:     cmp.eq p6,p7=PAL_RSE_INFO,r28
 (p7)   br.cond.sptk.few 1f
        mov r8=0                        /* status = 0 */
        mov r9=96                       /* num phys stacked */
        mov r10=0                       /* hints */
        mov r11=0
        br.cond.sptk.few rp
-1:     cmp.eq p6,p7=1,r28              /* PAL_CACHE_FLUSH */
+1:     cmp.eq p6,p7=PAL_CACHE_FLUSH,r28                /* PAL_CACHE_FLUSH */
 (p7)   br.cond.sptk.few 1f
        mov r9=ar.lc
        movl r8=524288                  /* flush 512k million cache lines (16MB) */
@@ -102,7 +107,7 @@ static:     cmp.eq p6,p7=6,r28              /* PAL_PTCE_INFO */
        mov ar.lc=r9
        mov r8=r0
        ;;
-1:     cmp.eq p6,p7=15,r28             /* PAL_PERF_MON_INFO */
+1:     cmp.eq p6,p7=PAL_PERF_MON_INFO,r28
 (p7)   br.cond.sptk.few 1f
        mov r8=0                        /* status = 0 */
        movl r9 =0x08122f04             /* generic=4 width=47 retired=8 cycles=18 */
@@ -138,6 +143,20 @@ static:    cmp.eq p6,p7=6,r28              /* PAL_PTCE_INFO */
        st8 [r29]=r0,16                 /* clear remaining bits  */
        st8 [r18]=r0,16                 /* clear remaining bits  */
        ;;
+1:     cmp.eq p6,p7=PAL_VM_SUMMARY,r28
+(p7)   br.cond.sptk.few 1f
+       mov     r8=0                    /* status = 0  */
+       movl    r9=0x2044040020F1865    /* num_tc_levels=2, num_unique_tcs=4 */
+                                       /* max_itr_entry=64, max_dtr_entry=64 */
+                                       /* hash_tag_id=2, max_pkr=15 */
+                                       /* key_size=24, phys_add_size=50, vw=1 */
+       movl    r10=0x183C              /* rid_size=24, impl_va_msb=60 */
+       ;;
+1:     cmp.eq p6,p7=PAL_MEM_ATTRIB,r28
+(p7)   br.cond.sptk.few 1f
+       mov     r8=0                    /* status = 0 */
+       mov     r9=0x80|0x01            /* NatPage|WB */
+       ;;
 1:     br.cond.sptk.few rp
 stacked:
        br.ret.sptk.few rp
index 0708edb06cc4da8190f76eb4e16e1bafcb2e6833..494fad6bf376dfdc845b2c25f3dcdfb40a02ac93 100644 (file)
@@ -1,6 +1,6 @@
 #include <asm/asmmacro.h>
 #include <asm/ia32.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/signal.h>
 #include <asm/thread_info.h>
 
index e29a8a55486a5e35fdc8eac3a2bb0acefc5cb062..3fa67ecebc838043c99fab4589e9d334dbd31604 100644 (file)
@@ -2327,7 +2327,7 @@ sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count)
        ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count);
        set_fs(old_fs);
 
-       if (!ret && offset && put_user(of, offset))
+       if (offset && put_user(of, offset))
                return -EFAULT;
 
        return ret;
index 7d1ae2982c53304c01e27eda01d285a0292507a3..f6a2342893418be2dd65fb55fc65798f58655bd8 100644 (file)
@@ -211,17 +211,41 @@ void foo(void)
 #endif
 
        BLANK();
-       DEFINE(IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET,
-              offsetof (struct ia64_mca_cpu, proc_state_dump));
-       DEFINE(IA64_MCA_CPU_STACK_OFFSET,
-              offsetof (struct ia64_mca_cpu, stack));
-       DEFINE(IA64_MCA_CPU_STACKFRAME_OFFSET,
-              offsetof (struct ia64_mca_cpu, stackframe));
-       DEFINE(IA64_MCA_CPU_RBSTORE_OFFSET,
-              offsetof (struct ia64_mca_cpu, rbstore));
+       DEFINE(IA64_MCA_CPU_MCA_STACK_OFFSET,
+              offsetof (struct ia64_mca_cpu, mca_stack));
        DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
               offsetof (struct ia64_mca_cpu, init_stack));
        BLANK();
+       DEFINE(IA64_SAL_OS_STATE_COMMON_OFFSET,
+              offsetof (struct ia64_sal_os_state, sal_ra));
+       DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET,
+              offsetof (struct ia64_sal_os_state, os_gp));
+       DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
+              offsetof (struct ia64_sal_os_state, pal_min_state));
+       DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET,
+              offsetof (struct ia64_sal_os_state, proc_state_param));
+       DEFINE(IA64_SAL_OS_STATE_SIZE,
+              sizeof (struct ia64_sal_os_state));
+       DEFINE(IA64_PMSA_GR_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_gr));
+       DEFINE(IA64_PMSA_BANK1_GR_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_bank1_gr));
+       DEFINE(IA64_PMSA_PR_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_pr));
+       DEFINE(IA64_PMSA_BR0_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_br0));
+       DEFINE(IA64_PMSA_RSC_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_rsc));
+       DEFINE(IA64_PMSA_IIP_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_iip));
+       DEFINE(IA64_PMSA_IPSR_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_ipsr));
+       DEFINE(IA64_PMSA_IFS_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_ifs));
+       DEFINE(IA64_PMSA_XIP_OFFSET,
+              offsetof (struct pal_min_state_area_s, pmsa_xip));
+       BLANK();
+
        /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
        DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
        DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
index 3c882102450999450b783d4b8642d4c74f4bae03..ba0b6a1f429fc315c17e4a8ace1cf8c5de8e0913 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/kregs.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/percpu.h>
 #include <asm/processor.h>
@@ -470,6 +470,29 @@ ENTRY(load_switch_stack)
        br.cond.sptk.many b7
 END(load_switch_stack)
 
+GLOBAL_ENTRY(prefetch_stack)
+       add r14 = -IA64_SWITCH_STACK_SIZE, sp
+       add r15 = IA64_TASK_THREAD_KSP_OFFSET, in0
+       ;;
+       ld8 r16 = [r15]                         // load next's stack pointer
+       lfetch.fault.excl [r14], 128
+       ;;
+       lfetch.fault.excl [r14], 128
+       lfetch.fault [r16], 128
+       ;;
+       lfetch.fault.excl [r14], 128
+       lfetch.fault [r16], 128
+       ;;
+       lfetch.fault.excl [r14], 128
+       lfetch.fault [r16], 128
+       ;;
+       lfetch.fault.excl [r14], 128
+       lfetch.fault [r16], 128
+       ;;
+       lfetch.fault [r16], 128
+       br.ret.sptk.many rp
+END(prefetch_switch_stack)
+
 GLOBAL_ENTRY(execve)
        mov r15=__NR_execve                     // put syscall number in place
        break __BREAK_SYSCALL
index 7d7684a369d38609a149e98db03084f898eacb90..2ddbac6f49993b4c0026ea6d12803f80b144f620 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/errno.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/percpu.h>
 #include <asm/thread_info.h>
 #include <asm/sal.h>
index 86948ce63e43ac8ac583eec74622434b86e5cd73..86064ca98952fce580151aa75a41f302ef64b4da 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/errno.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/sigcontext.h>
 #include <asm/system.h>
 #include <asm/unistd.h>
index 8d3a9291b47f835c43c25d916e400828d590798f..bfe65b2e862146ad9a16d1761e3f91ff69e05347 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/fpu.h>
 #include <asm/kregs.h>
 #include <asm/mmu_context.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/pal.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
index 3bb3a13c4047566d70057db9342c93da06fefd8e..c13ca0d49c4a04be59c32e2317149264fda092fa 100644 (file)
@@ -44,7 +44,7 @@
 #include <asm/break.h>
 #include <asm/ia32.h>
 #include <asm/kregs.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
@@ -69,7 +69,6 @@
 # define DBG_FAULT(i)
 #endif
 
-#define MINSTATE_VIRT  /* needed by minstate.h */
 #include "minstate.h"
 
 #define FAULT(n)                                                                       \
index 4ebbf3974381af2b7669c98c198d670c8e460fa7..6dc726ad71372954b36c02b93949f240ac794ee4 100644 (file)
@@ -48,6 +48,9 @@
  *            Delete dead variables and functions.
  *            Reorder to remove the need for forward declarations and to consolidate
  *            related code.
+ *
+ * 2005-08-12 Keith Owens <kaos@sgi.com>
+ *           Convert MCA/INIT handlers to use per event stacks and SAL/OS state.
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -77,6 +80,8 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 
+#include "entry.h"
+
 #if defined(IA64_MCA_DEBUG_INFO)
 # define IA64_MCA_DEBUG(fmt...)        printk(fmt)
 #else
@@ -84,9 +89,7 @@
 #endif
 
 /* Used by mca_asm.S */
-ia64_mca_sal_to_os_state_t     ia64_sal_to_os_handoff_state;
-ia64_mca_os_to_sal_state_t     ia64_os_to_sal_handoff_state;
-u64                            ia64_mca_serialize;
+u32                            ia64_mca_serialize;
 DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
 DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
 DEFINE_PER_CPU(u64, ia64_mca_pal_pte);     /* PTE to map PAL code */
@@ -95,8 +98,10 @@ DEFINE_PER_CPU(u64, ia64_mca_pal_base);    /* vaddr PAL code granule */
 unsigned long __per_cpu_mca[NR_CPUS];
 
 /* In mca_asm.S */
-extern void                    ia64_monarch_init_handler (void);
-extern void                    ia64_slave_init_handler (void);
+extern void                    ia64_os_init_dispatch_monarch (void);
+extern void                    ia64_os_init_dispatch_slave (void);
+
+static int monarch_cpu = -1;
 
 static ia64_mc_info_t          ia64_mc_info;
 
@@ -234,7 +239,8 @@ ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe)
  *  This function retrieves a specified error record type from SAL
  *  and wakes up any processes waiting for error records.
  *
- *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE/INIT)
+ *  Inputs  :   sal_info_type   (Type of error record MCA/CMC/CPE)
+ *              FIXME: remove MCA and irq_safe.
  */
 static void
 ia64_mca_log_sal_error_record(int sal_info_type)
@@ -242,7 +248,7 @@ ia64_mca_log_sal_error_record(int sal_info_type)
        u8 *buffer;
        sal_log_record_header_t *rh;
        u64 size;
-       int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT;
+       int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA;
 #ifdef IA64_MCA_DEBUG_INFO
        static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" };
 #endif
@@ -330,191 +336,6 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
 
 #endif /* CONFIG_ACPI */
 
-static void
-show_min_state (pal_min_state_area_t *minstate)
-{
-       u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri;
-       u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri;
-
-       printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits);
-       printk("pr\t\t%016lx\n", minstate->pmsa_pr);
-       printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0);
-       printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc);
-       printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip);
-       printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr);
-       printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs);
-       printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip);
-       printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr);
-       printk("xfs\t\t%016lx\n", minstate->pmsa_xfs);
-       printk("b1\t\t%016lx ", minstate->pmsa_br1);
-       print_symbol("%s\n", minstate->pmsa_br1);
-
-       printk("\nstatic registers r0-r15:\n");
-       printk(" r0- 3 %016lx %016lx %016lx %016lx\n",
-              0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]);
-       printk(" r4- 7 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_gr[3], minstate->pmsa_gr[4],
-              minstate->pmsa_gr[5], minstate->pmsa_gr[6]);
-       printk(" r8-11 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_gr[7], minstate->pmsa_gr[8],
-              minstate->pmsa_gr[9], minstate->pmsa_gr[10]);
-       printk("r12-15 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_gr[11], minstate->pmsa_gr[12],
-              minstate->pmsa_gr[13], minstate->pmsa_gr[14]);
-
-       printk("\nbank 0:\n");
-       printk("r16-19 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1],
-              minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]);
-       printk("r20-23 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5],
-              minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]);
-       printk("r24-27 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9],
-              minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]);
-       printk("r28-31 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13],
-              minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]);
-
-       printk("\nbank 1:\n");
-       printk("r16-19 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1],
-              minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]);
-       printk("r20-23 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5],
-              minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]);
-       printk("r24-27 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9],
-              minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]);
-       printk("r28-31 %016lx %016lx %016lx %016lx\n",
-              minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13],
-              minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]);
-}
-
-static void
-fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw)
-{
-       u64 *dst_banked, *src_banked, bit, shift, nat_bits;
-       int i;
-
-       /*
-        * First, update the pt-regs and switch-stack structures with the contents stored
-        * in the min-state area:
-        */
-       if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) {
-               pt->cr_ipsr = ms->pmsa_xpsr;
-               pt->cr_iip = ms->pmsa_xip;
-               pt->cr_ifs = ms->pmsa_xfs;
-       } else {
-               pt->cr_ipsr = ms->pmsa_ipsr;
-               pt->cr_iip = ms->pmsa_iip;
-               pt->cr_ifs = ms->pmsa_ifs;
-       }
-       pt->ar_rsc = ms->pmsa_rsc;
-       pt->pr = ms->pmsa_pr;
-       pt->r1 = ms->pmsa_gr[0];
-       pt->r2 = ms->pmsa_gr[1];
-       pt->r3 = ms->pmsa_gr[2];
-       sw->r4 = ms->pmsa_gr[3];
-       sw->r5 = ms->pmsa_gr[4];
-       sw->r6 = ms->pmsa_gr[5];
-       sw->r7 = ms->pmsa_gr[6];
-       pt->r8 = ms->pmsa_gr[7];
-       pt->r9 = ms->pmsa_gr[8];
-       pt->r10 = ms->pmsa_gr[9];
-       pt->r11 = ms->pmsa_gr[10];
-       pt->r12 = ms->pmsa_gr[11];
-       pt->r13 = ms->pmsa_gr[12];
-       pt->r14 = ms->pmsa_gr[13];
-       pt->r15 = ms->pmsa_gr[14];
-       dst_banked = &pt->r16;          /* r16-r31 are contiguous in struct pt_regs */
-       src_banked = ms->pmsa_bank1_gr;
-       for (i = 0; i < 16; ++i)
-               dst_banked[i] = src_banked[i];
-       pt->b0 = ms->pmsa_br0;
-       sw->b1 = ms->pmsa_br1;
-
-       /* construct the NaT bits for the pt-regs structure: */
-#      define PUT_NAT_BIT(dst, addr)                                   \
-       do {                                                            \
-               bit = nat_bits & 1; nat_bits >>= 1;                     \
-               shift = ((unsigned long) addr >> 3) & 0x3f;             \
-               dst = ((dst) & ~(1UL << shift)) | (bit << shift);       \
-       } while (0)
-
-       /* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */
-       shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f;
-       nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift));
-
-       PUT_NAT_BIT(sw->caller_unat, &pt->r1);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r2);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r3);
-       PUT_NAT_BIT(sw->ar_unat, &sw->r4);
-       PUT_NAT_BIT(sw->ar_unat, &sw->r5);
-       PUT_NAT_BIT(sw->ar_unat, &sw->r6);
-       PUT_NAT_BIT(sw->ar_unat, &sw->r7);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r8);  PUT_NAT_BIT(sw->caller_unat, &pt->r9);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r10); PUT_NAT_BIT(sw->caller_unat, &pt->r11);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r12); PUT_NAT_BIT(sw->caller_unat, &pt->r13);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r14); PUT_NAT_BIT(sw->caller_unat, &pt->r15);
-       nat_bits >>= 16;        /* skip over bank0 NaT bits */
-       PUT_NAT_BIT(sw->caller_unat, &pt->r16); PUT_NAT_BIT(sw->caller_unat, &pt->r17);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r18); PUT_NAT_BIT(sw->caller_unat, &pt->r19);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r20); PUT_NAT_BIT(sw->caller_unat, &pt->r21);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r22); PUT_NAT_BIT(sw->caller_unat, &pt->r23);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r24); PUT_NAT_BIT(sw->caller_unat, &pt->r25);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r26); PUT_NAT_BIT(sw->caller_unat, &pt->r27);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r28); PUT_NAT_BIT(sw->caller_unat, &pt->r29);
-       PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31);
-}
-
-static void
-init_handler_platform (pal_min_state_area_t *ms,
-                      struct pt_regs *pt, struct switch_stack *sw)
-{
-       struct unw_frame_info info;
-
-       /* if a kernel debugger is available call it here else just dump the registers */
-
-       /*
-        * Wait for a bit.  On some machines (e.g., HP's zx2000 and zx6000, INIT can be
-        * generated via the BMC's command-line interface, but since the console is on the
-        * same serial line, the user will need some time to switch out of the BMC before
-        * the dump begins.
-        */
-       printk("Delaying for 5 seconds...\n");
-       udelay(5*1000000);
-       show_min_state(ms);
-
-       printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm);
-       fetch_min_state(ms, pt, sw);
-       unw_init_from_interruption(&info, current, pt, sw);
-       ia64_do_show_stack(&info, NULL);
-
-#ifdef CONFIG_SMP
-       /* read_trylock() would be handy... */
-       if (!tasklist_lock.write_lock)
-               read_lock(&tasklist_lock);
-#endif
-       {
-               struct task_struct *g, *t;
-               do_each_thread (g, t) {
-                       if (t == current)
-                               continue;
-
-                       printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
-                       show_stack(t, NULL);
-               } while_each_thread (g, t);
-       }
-#ifdef CONFIG_SMP
-       if (!tasklist_lock.write_lock)
-               read_unlock(&tasklist_lock);
-#endif
-
-       printk("\nINIT dump complete.  Please reboot now.\n");
-       while (1);                      /* hang city if no debugger */
-}
-
 #ifdef CONFIG_ACPI
 /*
  * ia64_mca_register_cpev
@@ -656,42 +477,6 @@ ia64_mca_cmc_vector_enable_keventd(void *unused)
        on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0);
 }
 
-/*
- * ia64_mca_wakeup_ipi_wait
- *
- *     Wait for the inter-cpu interrupt to be sent by the
- *     monarch processor once it is done with handling the
- *     MCA.
- *
- *  Inputs  :   None
- *  Outputs :   None
- */
-static void
-ia64_mca_wakeup_ipi_wait(void)
-{
-       int     irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6);
-       int     irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f);
-       u64     irr = 0;
-
-       do {
-               switch(irr_num) {
-                     case 0:
-                       irr = ia64_getreg(_IA64_REG_CR_IRR0);
-                       break;
-                     case 1:
-                       irr = ia64_getreg(_IA64_REG_CR_IRR1);
-                       break;
-                     case 2:
-                       irr = ia64_getreg(_IA64_REG_CR_IRR2);
-                       break;
-                     case 3:
-                       irr = ia64_getreg(_IA64_REG_CR_IRR3);
-                       break;
-               }
-               cpu_relax();
-       } while (!(irr & (1UL << irr_bit))) ;
-}
-
 /*
  * ia64_mca_wakeup
  *
@@ -757,11 +542,9 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
         */
        ia64_sal_mc_rendez();
 
-       /* Wait for the wakeup IPI from the monarch
-        * This waiting is done by polling on the wakeup-interrupt
-        * vector bit in the processor's IRRs
-        */
-       ia64_mca_wakeup_ipi_wait();
+       /* Wait for the monarch cpu to exit. */
+       while (monarch_cpu != -1)
+              cpu_relax();     /* spin until monarch leaves */
 
        /* Enable all interrupts */
        local_irq_restore(flags);
@@ -789,53 +572,13 @@ ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
        return IRQ_HANDLED;
 }
 
-/*
- * ia64_return_to_sal_check
- *
- *     This is function called before going back from the OS_MCA handler
- *     to the OS_MCA dispatch code which finally takes the control back
- *     to the SAL.
- *     The main purpose of this routine is to setup the OS_MCA to SAL
- *     return state which can be used by the OS_MCA dispatch code
- *     just before going back to SAL.
- *
- *  Inputs  :   None
- *  Outputs :   None
- */
-
-static void
-ia64_return_to_sal_check(int recover)
-{
-
-       /* Copy over some relevant stuff from the sal_to_os_mca_handoff
-        * so that it can be used at the time of os_mca_to_sal_handoff
-        */
-       ia64_os_to_sal_handoff_state.imots_sal_gp =
-               ia64_sal_to_os_handoff_state.imsto_sal_gp;
-
-       ia64_os_to_sal_handoff_state.imots_sal_check_ra =
-               ia64_sal_to_os_handoff_state.imsto_sal_check_ra;
-
-       if (recover)
-               ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED;
-       else
-               ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT;
-
-       /* Default = tell SAL to return to same context */
-       ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT;
-
-       ia64_os_to_sal_handoff_state.imots_new_min_state =
-               (u64 *)ia64_sal_to_os_handoff_state.pal_min_state;
-
-}
-
 /* Function pointer for extra MCA recovery */
 int (*ia64_mca_ucmc_extension)
-       (void*,ia64_mca_sal_to_os_state_t*,ia64_mca_os_to_sal_state_t*)
+       (void*,struct ia64_sal_os_state*)
        = NULL;
 
 int
-ia64_reg_MCA_extension(void *fn)
+ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *))
 {
        if (ia64_mca_ucmc_extension)
                return 1;
@@ -854,8 +597,321 @@ ia64_unreg_MCA_extension(void)
 EXPORT_SYMBOL(ia64_reg_MCA_extension);
 EXPORT_SYMBOL(ia64_unreg_MCA_extension);
 
+
+static inline void
+copy_reg(const u64 *fr, u64 fnat, u64 *tr, u64 *tnat)
+{
+       u64 fslot, tslot, nat;
+       *tr = *fr;
+       fslot = ((unsigned long)fr >> 3) & 63;
+       tslot = ((unsigned long)tr >> 3) & 63;
+       *tnat &= ~(1UL << tslot);
+       nat = (fnat >> fslot) & 1;
+       *tnat |= (nat << tslot);
+}
+
+/* On entry to this routine, we are running on the per cpu stack, see
+ * mca_asm.h.  The original stack has not been touched by this event.  Some of
+ * the original stack's registers will be in the RBS on this stack.  This stack
+ * also contains a partial pt_regs and switch_stack, the rest of the data is in
+ * PAL minstate.
+ *
+ * The first thing to do is modify the original stack to look like a blocked
+ * task so we can run backtrace on the original task.  Also mark the per cpu
+ * stack as current to ensure that we use the correct task state, it also means
+ * that we can do backtrace on the MCA/INIT handler code itself.
+ */
+
+static task_t *
+ia64_mca_modify_original_stack(struct pt_regs *regs,
+               const struct switch_stack *sw,
+               struct ia64_sal_os_state *sos,
+               const char *type)
+{
+       char *p, comm[sizeof(current->comm)];
+       ia64_va va;
+       extern char ia64_leave_kernel[];        /* Need asm address, not function descriptor */
+       const pal_min_state_area_t *ms = sos->pal_min_state;
+       task_t *previous_current;
+       struct pt_regs *old_regs;
+       struct switch_stack *old_sw;
+       unsigned size = sizeof(struct pt_regs) +
+                       sizeof(struct switch_stack) + 16;
+       u64 *old_bspstore, *old_bsp;
+       u64 *new_bspstore, *new_bsp;
+       u64 old_unat, old_rnat, new_rnat, nat;
+       u64 slots, loadrs = regs->loadrs;
+       u64 r12 = ms->pmsa_gr[12-1], r13 = ms->pmsa_gr[13-1];
+       u64 ar_bspstore = regs->ar_bspstore;
+       u64 ar_bsp = regs->ar_bspstore + (loadrs >> 16);
+       const u64 *bank;
+       const char *msg;
+       int cpu = smp_processor_id();
+
+       previous_current = curr_task(cpu);
+       set_curr_task(cpu, current);
+       if ((p = strchr(current->comm, ' ')))
+               *p = '\0';
+
+       /* Best effort attempt to cope with MCA/INIT delivered while in
+        * physical mode.
+        */
+       regs->cr_ipsr = ms->pmsa_ipsr;
+       if (ia64_psr(regs)->dt == 0) {
+               va.l = r12;
+               if (va.f.reg == 0) {
+                       va.f.reg = 7;
+                       r12 = va.l;
+               }
+               va.l = r13;
+               if (va.f.reg == 0) {
+                       va.f.reg = 7;
+                       r13 = va.l;
+               }
+       }
+       if (ia64_psr(regs)->rt == 0) {
+               va.l = ar_bspstore;
+               if (va.f.reg == 0) {
+                       va.f.reg = 7;
+                       ar_bspstore = va.l;
+               }
+               va.l = ar_bsp;
+               if (va.f.reg == 0) {
+                       va.f.reg = 7;
+                       ar_bsp = va.l;
+               }
+       }
+
+       /* mca_asm.S ia64_old_stack() cannot assume that the dirty registers
+        * have been copied to the old stack, the old stack may fail the
+        * validation tests below.  So ia64_old_stack() must restore the dirty
+        * registers from the new stack.  The old and new bspstore probably
+        * have different alignments, so loadrs calculated on the old bsp
+        * cannot be used to restore from the new bsp.  Calculate a suitable
+        * loadrs for the new stack and save it in the new pt_regs, where
+        * ia64_old_stack() can get it.
+        */
+       old_bspstore = (u64 *)ar_bspstore;
+       old_bsp = (u64 *)ar_bsp;
+       slots = ia64_rse_num_regs(old_bspstore, old_bsp);
+       new_bspstore = (u64 *)((u64)current + IA64_RBS_OFFSET);
+       new_bsp = ia64_rse_skip_regs(new_bspstore, slots);
+       regs->loadrs = (new_bsp - new_bspstore) * 8 << 16;
+
+       /* Verify the previous stack state before we change it */
+       if (user_mode(regs)) {
+               msg = "occurred in user space";
+               goto no_mod;
+       }
+       if (r13 != sos->prev_IA64_KR_CURRENT) {
+               msg = "inconsistent previous current and r13";
+               goto no_mod;
+       }
+       if ((r12 - r13) >= KERNEL_STACK_SIZE) {
+               msg = "inconsistent r12 and r13";
+               goto no_mod;
+       }
+       if ((ar_bspstore - r13) >= KERNEL_STACK_SIZE) {
+               msg = "inconsistent ar.bspstore and r13";
+               goto no_mod;
+       }
+       va.p = old_bspstore;
+       if (va.f.reg < 5) {
+               msg = "old_bspstore is in the wrong region";
+               goto no_mod;
+       }
+       if ((ar_bsp - r13) >= KERNEL_STACK_SIZE) {
+               msg = "inconsistent ar.bsp and r13";
+               goto no_mod;
+       }
+       size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8;
+       if (ar_bspstore + size > r12) {
+               msg = "no room for blocked state";
+               goto no_mod;
+       }
+
+       /* Change the comm field on the MCA/INT task to include the pid that
+        * was interrupted, it makes for easier debugging.  If that pid was 0
+        * (swapper or nested MCA/INIT) then use the start of the previous comm
+        * field suffixed with its cpu.
+        */
+       if (previous_current->pid)
+               snprintf(comm, sizeof(comm), "%s %d",
+                       current->comm, previous_current->pid);
+       else {
+               int l;
+               if ((p = strchr(previous_current->comm, ' ')))
+                       l = p - previous_current->comm;
+               else
+                       l = strlen(previous_current->comm);
+               snprintf(comm, sizeof(comm), "%s %*s %d",
+                       current->comm, l, previous_current->comm,
+                       previous_current->thread_info->cpu);
+       }
+       memcpy(current->comm, comm, sizeof(current->comm));
+
+       /* Make the original task look blocked.  First stack a struct pt_regs,
+        * describing the state at the time of interrupt.  mca_asm.S built a
+        * partial pt_regs, copy it and fill in the blanks using minstate.
+        */
+       p = (char *)r12 - sizeof(*regs);
+       old_regs = (struct pt_regs *)p;
+       memcpy(old_regs, regs, sizeof(*regs));
+       /* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
+        * pmsa_{xip,xpsr,xfs}
+        */
+       if (ia64_psr(regs)->ic) {
+               old_regs->cr_iip = ms->pmsa_iip;
+               old_regs->cr_ipsr = ms->pmsa_ipsr;
+               old_regs->cr_ifs = ms->pmsa_ifs;
+       } else {
+               old_regs->cr_iip = ms->pmsa_xip;
+               old_regs->cr_ipsr = ms->pmsa_xpsr;
+               old_regs->cr_ifs = ms->pmsa_xfs;
+       }
+       old_regs->pr = ms->pmsa_pr;
+       old_regs->b0 = ms->pmsa_br0;
+       old_regs->loadrs = loadrs;
+       old_regs->ar_rsc = ms->pmsa_rsc;
+       old_unat = old_regs->ar_unat;
+       copy_reg(&ms->pmsa_gr[1-1], ms->pmsa_nat_bits, &old_regs->r1, &old_unat);
+       copy_reg(&ms->pmsa_gr[2-1], ms->pmsa_nat_bits, &old_regs->r2, &old_unat);
+       copy_reg(&ms->pmsa_gr[3-1], ms->pmsa_nat_bits, &old_regs->r3, &old_unat);
+       copy_reg(&ms->pmsa_gr[8-1], ms->pmsa_nat_bits, &old_regs->r8, &old_unat);
+       copy_reg(&ms->pmsa_gr[9-1], ms->pmsa_nat_bits, &old_regs->r9, &old_unat);
+       copy_reg(&ms->pmsa_gr[10-1], ms->pmsa_nat_bits, &old_regs->r10, &old_unat);
+       copy_reg(&ms->pmsa_gr[11-1], ms->pmsa_nat_bits, &old_regs->r11, &old_unat);
+       copy_reg(&ms->pmsa_gr[12-1], ms->pmsa_nat_bits, &old_regs->r12, &old_unat);
+       copy_reg(&ms->pmsa_gr[13-1], ms->pmsa_nat_bits, &old_regs->r13, &old_unat);
+       copy_reg(&ms->pmsa_gr[14-1], ms->pmsa_nat_bits, &old_regs->r14, &old_unat);
+       copy_reg(&ms->pmsa_gr[15-1], ms->pmsa_nat_bits, &old_regs->r15, &old_unat);
+       if (ia64_psr(old_regs)->bn)
+               bank = ms->pmsa_bank1_gr;
+       else
+               bank = ms->pmsa_bank0_gr;
+       copy_reg(&bank[16-16], ms->pmsa_nat_bits, &old_regs->r16, &old_unat);
+       copy_reg(&bank[17-16], ms->pmsa_nat_bits, &old_regs->r17, &old_unat);
+       copy_reg(&bank[18-16], ms->pmsa_nat_bits, &old_regs->r18, &old_unat);
+       copy_reg(&bank[19-16], ms->pmsa_nat_bits, &old_regs->r19, &old_unat);
+       copy_reg(&bank[20-16], ms->pmsa_nat_bits, &old_regs->r20, &old_unat);
+       copy_reg(&bank[21-16], ms->pmsa_nat_bits, &old_regs->r21, &old_unat);
+       copy_reg(&bank[22-16], ms->pmsa_nat_bits, &old_regs->r22, &old_unat);
+       copy_reg(&bank[23-16], ms->pmsa_nat_bits, &old_regs->r23, &old_unat);
+       copy_reg(&bank[24-16], ms->pmsa_nat_bits, &old_regs->r24, &old_unat);
+       copy_reg(&bank[25-16], ms->pmsa_nat_bits, &old_regs->r25, &old_unat);
+       copy_reg(&bank[26-16], ms->pmsa_nat_bits, &old_regs->r26, &old_unat);
+       copy_reg(&bank[27-16], ms->pmsa_nat_bits, &old_regs->r27, &old_unat);
+       copy_reg(&bank[28-16], ms->pmsa_nat_bits, &old_regs->r28, &old_unat);
+       copy_reg(&bank[29-16], ms->pmsa_nat_bits, &old_regs->r29, &old_unat);
+       copy_reg(&bank[30-16], ms->pmsa_nat_bits, &old_regs->r30, &old_unat);
+       copy_reg(&bank[31-16], ms->pmsa_nat_bits, &old_regs->r31, &old_unat);
+
+       /* Next stack a struct switch_stack.  mca_asm.S built a partial
+        * switch_stack, copy it and fill in the blanks using pt_regs and
+        * minstate.
+        *
+        * In the synthesized switch_stack, b0 points to ia64_leave_kernel,
+        * ar.pfs is set to 0.
+        *
+        * unwind.c::unw_unwind() does special processing for interrupt frames.
+        * It checks if the PRED_NON_SYSCALL predicate is set, if the predicate
+        * is clear then unw_unwind() does _not_ adjust bsp over pt_regs.  Not
+        * that this is documented, of course.  Set PRED_NON_SYSCALL in the
+        * switch_stack on the original stack so it will unwind correctly when
+        * unwind.c reads pt_regs.
+        *
+        * thread.ksp is updated to point to the synthesized switch_stack.
+        */
+       p -= sizeof(struct switch_stack);
+       old_sw = (struct switch_stack *)p;
+       memcpy(old_sw, sw, sizeof(*sw));
+       old_sw->caller_unat = old_unat;
+       old_sw->ar_fpsr = old_regs->ar_fpsr;
+       copy_reg(&ms->pmsa_gr[4-1], ms->pmsa_nat_bits, &old_sw->r4, &old_unat);
+       copy_reg(&ms->pmsa_gr[5-1], ms->pmsa_nat_bits, &old_sw->r5, &old_unat);
+       copy_reg(&ms->pmsa_gr[6-1], ms->pmsa_nat_bits, &old_sw->r6, &old_unat);
+       copy_reg(&ms->pmsa_gr[7-1], ms->pmsa_nat_bits, &old_sw->r7, &old_unat);
+       old_sw->b0 = (u64)ia64_leave_kernel;
+       old_sw->b1 = ms->pmsa_br1;
+       old_sw->ar_pfs = 0;
+       old_sw->ar_unat = old_unat;
+       old_sw->pr = old_regs->pr | (1UL << PRED_NON_SYSCALL);
+       previous_current->thread.ksp = (u64)p - 16;
+
+       /* Finally copy the original stack's registers back to its RBS.
+        * Registers from ar.bspstore through ar.bsp at the time of the event
+        * are in the current RBS, copy them back to the original stack.  The
+        * copy must be done register by register because the original bspstore
+        * and the current one have different alignments, so the saved RNAT
+        * data occurs at different places.
+        *
+        * mca_asm does cover, so the old_bsp already includes all registers at
+        * the time of MCA/INIT.  It also does flushrs, so all registers before
+        * this function have been written to backing store on the MCA/INIT
+        * stack.
+        */
+       new_rnat = ia64_get_rnat(ia64_rse_rnat_addr(new_bspstore));
+       old_rnat = regs->ar_rnat;
+       while (slots--) {
+               if (ia64_rse_is_rnat_slot(new_bspstore)) {
+                       new_rnat = ia64_get_rnat(new_bspstore++);
+               }
+               if (ia64_rse_is_rnat_slot(old_bspstore)) {
+                       *old_bspstore++ = old_rnat;
+                       old_rnat = 0;
+               }
+               nat = (new_rnat >> ia64_rse_slot_num(new_bspstore)) & 1UL;
+               old_rnat &= ~(1UL << ia64_rse_slot_num(old_bspstore));
+               old_rnat |= (nat << ia64_rse_slot_num(old_bspstore));
+               *old_bspstore++ = *new_bspstore++;
+       }
+       old_sw->ar_bspstore = (unsigned long)old_bspstore;
+       old_sw->ar_rnat = old_rnat;
+
+       sos->prev_task = previous_current;
+       return previous_current;
+
+no_mod:
+       printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
+                       smp_processor_id(), type, msg);
+       return previous_current;
+}
+
+/* The monarch/slave interaction is based on monarch_cpu and requires that all
+ * slaves have entered rendezvous before the monarch leaves.  If any cpu has
+ * not entered rendezvous yet then wait a bit.  The assumption is that any
+ * slave that has not rendezvoused after a reasonable time is never going to do
+ * so.  In this context, slave includes cpus that respond to the MCA rendezvous
+ * interrupt, as well as cpus that receive the INIT slave event.
+ */
+
+static void
+ia64_wait_for_slaves(int monarch)
+{
+       int c, wait = 0;
+       for_each_online_cpu(c) {
+               if (c == monarch)
+                       continue;
+               if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
+                       udelay(1000);           /* short wait first */
+                       wait = 1;
+                       break;
+               }
+       }
+       if (!wait)
+               return;
+       for_each_online_cpu(c) {
+               if (c == monarch)
+                       continue;
+               if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) {
+                       udelay(5*1000000);      /* wait 5 seconds for slaves (arbitrary) */
+                       break;
+               }
+       }
+}
+
 /*
- * ia64_mca_ucmc_handler
+ * ia64_mca_handler
  *
  *     This is uncorrectable machine check handler called from OS_MCA
  *     dispatch code which is in turn called from SAL_CHECK().
@@ -866,16 +922,28 @@ EXPORT_SYMBOL(ia64_unreg_MCA_extension);
  *     further MCA logging is enabled by clearing logs.
  *     Monarch also has the duty of sending wakeup-IPIs to pull the
  *     slave processors out of rendezvous spinloop.
- *
- *  Inputs  :   None
- *  Outputs :   None
  */
 void
-ia64_mca_ucmc_handler(void)
+ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
+                struct ia64_sal_os_state *sos)
 {
        pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
-               &ia64_sal_to_os_handoff_state.proc_state_param;
-       int recover; 
+               &sos->proc_state_param;
+       int recover, cpu = smp_processor_id();
+       task_t *previous_current;
+
+       oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
+       previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
+       monarch_cpu = cpu;
+       ia64_wait_for_slaves(cpu);
+
+       /* Wakeup all the processors which are spinning in the rendezvous loop.
+        * They will leave SAL, then spin in the OS with interrupts disabled
+        * until this monarch cpu leaves the MCA handler.  That gets control
+        * back to the OS so we can backtrace the other cpus, backtrace when
+        * spinning in SAL does not work.
+        */
+       ia64_mca_wakeup_all();
 
        /* Get the MCA error record and log it */
        ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
@@ -883,25 +951,20 @@ ia64_mca_ucmc_handler(void)
        /* TLB error is only exist in this SAL error record */
        recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
        /* other error recovery */
-          || (ia64_mca_ucmc_extension 
+          || (ia64_mca_ucmc_extension
                && ia64_mca_ucmc_extension(
                        IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),
-                       &ia64_sal_to_os_handoff_state,
-                       &ia64_os_to_sal_handoff_state)); 
+                       sos));
 
        if (recover) {
                sal_log_record_header_t *rh = IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA);
                rh->severity = sal_log_severity_corrected;
                ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
+               sos->os_status = IA64_MCA_CORRECTED;
        }
-       /*
-        *  Wakeup all the processors which are spinning in the rendezvous
-        *  loop.
-        */
-       ia64_mca_wakeup_all();
 
-       /* Return to SAL */
-       ia64_return_to_sal_check(recover);
+       set_curr_task(cpu, previous_current);
+       monarch_cpu = -1;
 }
 
 static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL);
@@ -1125,34 +1188,114 @@ ia64_mca_cpe_poll (unsigned long dummy)
 /*
  * C portion of the OS INIT handler
  *
- * Called from ia64_monarch_init_handler
- *
- * Inputs: pointer to pt_regs where processor info was saved.
+ * Called from ia64_os_init_dispatch
  *
- * Returns:
- *   0 if SAL must warm boot the System
- *   1 if SAL must return to interrupted context using PAL_MC_RESUME
+ * Inputs: pointer to pt_regs where processor info was saved.  SAL/OS state for
+ * this event.  This code is used for both monarch and slave INIT events, see
+ * sos->monarch.
  *
+ * All INIT events switch to the INIT stack and change the previous process to
+ * blocked status.  If one of the INIT events is the monarch then we are
+ * probably processing the nmi button/command.  Use the monarch cpu to dump all
+ * the processes.  The slave INIT events all spin until the monarch cpu
+ * returns.  We can also get INIT slave events for MCA, in which case the MCA
+ * process is the monarch.
  */
+
 void
-ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
+ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
+                 struct ia64_sal_os_state *sos)
 {
-       pal_min_state_area_t *ms;
+       static atomic_t slaves;
+       static atomic_t monarchs;
+       task_t *previous_current;
+       int cpu = smp_processor_id(), c;
+       struct task_struct *g, *t;
 
-       oops_in_progress = 1;   /* avoid deadlock in printk, but it makes recovery dodgy */
+       oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
        console_loglevel = 15;  /* make sure printks make it to console */
 
-       printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
-               ia64_sal_to_os_handoff_state.proc_state_param);
+       printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
+               sos->proc_state_param, cpu, sos->monarch);
+       salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
 
-       /*
-        * Address of minstate area provided by PAL is physical,
-        * uncacheable (bit 63 set). Convert to Linux virtual
-        * address in region 6.
+       previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "INIT");
+       sos->os_status = IA64_INIT_RESUME;
+
+       /* FIXME: Workaround for broken proms that drive all INIT events as
+        * slaves.  The last slave that enters is promoted to be a monarch.
+        * Remove this code in September 2006, that gives platforms a year to
+        * fix their proms and get their customers updated.
         */
-       ms = (pal_min_state_area_t *)(ia64_sal_to_os_handoff_state.pal_min_state | (6ul<<61));
+       if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {
+               printk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
+                      __FUNCTION__, cpu);
+               atomic_dec(&slaves);
+               sos->monarch = 1;
+       }
+
+       /* FIXME: Workaround for broken proms that drive all INIT events as
+        * monarchs.  Second and subsequent monarchs are demoted to slaves.
+        * Remove this code in September 2006, that gives platforms a year to
+        * fix their proms and get their customers updated.
+        */
+       if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {
+               printk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
+                              __FUNCTION__, cpu);
+               atomic_dec(&monarchs);
+               sos->monarch = 0;
+       }
 
-       init_handler_platform(ms, pt, sw);      /* call platform specific routines */
+       if (!sos->monarch) {
+               ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_INIT;
+               while (monarch_cpu == -1)
+                      cpu_relax();     /* spin until monarch enters */
+               while (monarch_cpu != -1)
+                      cpu_relax();     /* spin until monarch leaves */
+               printk("Slave on cpu %d returning to normal service.\n", cpu);
+               set_curr_task(cpu, previous_current);
+               ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+               atomic_dec(&slaves);
+               return;
+       }
+
+       monarch_cpu = cpu;
+
+       /*
+        * Wait for a bit.  On some machines (e.g., HP's zx2000 and zx6000, INIT can be
+        * generated via the BMC's command-line interface, but since the console is on the
+        * same serial line, the user will need some time to switch out of the BMC before
+        * the dump begins.
+        */
+       printk("Delaying for 5 seconds...\n");
+       udelay(5*1000000);
+       ia64_wait_for_slaves(cpu);
+       printk(KERN_ERR "Processes interrupted by INIT -");
+       for_each_online_cpu(c) {
+               struct ia64_sal_os_state *s;
+               t = __va(__per_cpu_mca[c] + IA64_MCA_CPU_INIT_STACK_OFFSET);
+               s = (struct ia64_sal_os_state *)((char *)t + MCA_SOS_OFFSET);
+               g = s->prev_task;
+               if (g) {
+                       if (g->pid)
+                               printk(" %d", g->pid);
+                       else
+                               printk(" %d (cpu %d task 0x%p)", g->pid, task_cpu(g), g);
+               }
+       }
+       printk("\n\n");
+       if (read_trylock(&tasklist_lock)) {
+               do_each_thread (g, t) {
+                       printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
+                       show_stack(t, NULL);
+               } while_each_thread (g, t);
+               read_unlock(&tasklist_lock);
+       }
+       printk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
+       atomic_dec(&monarchs);
+       set_curr_task(cpu, previous_current);
+       monarch_cpu = -1;
+       return;
 }
 
 static int __init
@@ -1202,6 +1345,34 @@ static struct irqaction mca_cpep_irqaction = {
 };
 #endif /* CONFIG_ACPI */
 
+/* Minimal format of the MCA/INIT stacks.  The pseudo processes that run on
+ * these stacks can never sleep, they cannot return from the kernel to user
+ * space, they do not appear in a normal ps listing.  So there is no need to
+ * format most of the fields.
+ */
+
+static void
+format_mca_init_stack(void *mca_data, unsigned long offset,
+               const char *type, int cpu)
+{
+       struct task_struct *p = (struct task_struct *)((char *)mca_data + offset);
+       struct thread_info *ti;
+       memset(p, 0, KERNEL_STACK_SIZE);
+       ti = (struct thread_info *)((char *)p + IA64_TASK_SIZE);
+       ti->flags = _TIF_MCA_INIT;
+       ti->preempt_count = 1;
+       ti->task = p;
+       ti->cpu = cpu;
+       p->thread_info = ti;
+       p->state = TASK_UNINTERRUPTIBLE;
+       __set_bit(cpu, &p->cpus_allowed);
+       INIT_LIST_HEAD(&p->tasks);
+       p->parent = p->real_parent = p->group_leader = p;
+       INIT_LIST_HEAD(&p->children);
+       INIT_LIST_HEAD(&p->sibling);
+       strncpy(p->comm, type, sizeof(p->comm)-1);
+}
+
 /* Do per-CPU MCA-related initialization.  */
 
 void __devinit
@@ -1214,19 +1385,28 @@ ia64_mca_cpu_init(void *cpu_data)
                int cpu;
 
                mca_data = alloc_bootmem(sizeof(struct ia64_mca_cpu)
-                                        * NR_CPUS);
+                                        * NR_CPUS + KERNEL_STACK_SIZE);
+               mca_data = (void *)(((unsigned long)mca_data +
+                                       KERNEL_STACK_SIZE - 1) &
+                               (-KERNEL_STACK_SIZE));
                for (cpu = 0; cpu < NR_CPUS; cpu++) {
+                       format_mca_init_stack(mca_data,
+                                       offsetof(struct ia64_mca_cpu, mca_stack),
+                                       "MCA", cpu);
+                       format_mca_init_stack(mca_data,
+                                       offsetof(struct ia64_mca_cpu, init_stack),
+                                       "INIT", cpu);
                        __per_cpu_mca[cpu] = __pa(mca_data);
                        mca_data += sizeof(struct ia64_mca_cpu);
                }
        }
 
-        /*
-         * The MCA info structure was allocated earlier and its
-         * physical address saved in __per_cpu_mca[cpu].  Copy that
-         * address * to ia64_mca_data so we can access it as a per-CPU
-         * variable.
-         */
+       /*
+        * The MCA info structure was allocated earlier and its
+        * physical address saved in __per_cpu_mca[cpu].  Copy that
+        * address * to ia64_mca_data so we can access it as a per-CPU
+        * variable.
+        */
        __get_cpu_var(ia64_mca_data) = __per_cpu_mca[smp_processor_id()];
 
        /*
@@ -1236,11 +1416,11 @@ ia64_mca_cpu_init(void *cpu_data)
        __get_cpu_var(ia64_mca_per_cpu_pte) =
                pte_val(mk_pte_phys(__pa(cpu_data), PAGE_KERNEL));
 
-        /*
-         * Also, stash away a copy of the PAL address and the PTE
-         * needed to map it.
-         */
-        pal_vaddr = efi_get_pal_addr();
+       /*
+        * Also, stash away a copy of the PAL address and the PTE
+        * needed to map it.
+        */
+       pal_vaddr = efi_get_pal_addr();
        if (!pal_vaddr)
                return;
        __get_cpu_var(ia64_mca_pal_base) =
@@ -1272,8 +1452,8 @@ ia64_mca_cpu_init(void *cpu_data)
 void __init
 ia64_mca_init(void)
 {
-       ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler;
-       ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler;
+       ia64_fptr_t *init_hldlr_ptr_monarch = (ia64_fptr_t *)ia64_os_init_dispatch_monarch;
+       ia64_fptr_t *init_hldlr_ptr_slave = (ia64_fptr_t *)ia64_os_init_dispatch_slave;
        ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch;
        int i;
        s64 rc;
@@ -1351,9 +1531,9 @@ ia64_mca_init(void)
         * XXX - disable SAL checksum by setting size to 0, should be
         * size of the actual init handler in mca_asm.S.
         */
-       ia64_mc_info.imi_monarch_init_handler           = ia64_tpa(mon_init_ptr->fp);
+       ia64_mc_info.imi_monarch_init_handler           = ia64_tpa(init_hldlr_ptr_monarch->fp);
        ia64_mc_info.imi_monarch_init_handler_size      = 0;
-       ia64_mc_info.imi_slave_init_handler             = ia64_tpa(slave_init_ptr->fp);
+       ia64_mc_info.imi_slave_init_handler             = ia64_tpa(init_hldlr_ptr_slave->fp);
        ia64_mc_info.imi_slave_init_handler_size        = 0;
 
        IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__,
index ef3fd7265b67c8b6152ad3557162b8488d142231..499a065f4e6019544c957d72a8c5168fa6461803 100644 (file)
@@ -16,6 +16,9 @@
 // 04/11/12 Russ Anderson <rja@sgi.com>
 //                Added per cpu MCA/INIT stack save areas.
 //
+// 12/08/05 Keith Owens <kaos@sgi.com>
+//                Use per cpu MCA/INIT stacks for all data.
+//
 #include <linux/config.h>
 #include <linux/threads.h>
 
 #include <asm/mca_asm.h>
 #include <asm/mca.h>
 
-/*
- * When we get a machine check, the kernel stack pointer is no longer
- * valid, so we need to set a new stack pointer.
- */
-#define        MINSTATE_PHYS   /* Make sure stack access is physical for MINSTATE */
-
-/*
- * Needed for return context to SAL
- */
-#define IA64_MCA_SAME_CONTEXT  0
-#define IA64_MCA_COLD_BOOT     -2
-
-#include "minstate.h"
-
-/*
- * SAL_TO_OS_MCA_HANDOFF_STATE (SAL 3.0 spec)
- *             1. GR1 = OS GP
- *             2. GR8 = PAL_PROC physical address
- *             3. GR9 = SAL_PROC physical address
- *             4. GR10 = SAL GP (physical)
- *             5. GR11 = Rendez state
- *             6. GR12 = Return address to location within SAL_CHECK
- */
-#define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp)         \
-       LOAD_PHYSICAL(p0, _tmp, ia64_sal_to_os_handoff_state);; \
-       st8     [_tmp]=r1,0x08;;                        \
-       st8     [_tmp]=r8,0x08;;                        \
-       st8     [_tmp]=r9,0x08;;                        \
-       st8     [_tmp]=r10,0x08;;                       \
-       st8     [_tmp]=r11,0x08;;                       \
-       st8     [_tmp]=r12,0x08;;                       \
-       st8     [_tmp]=r17,0x08;;                       \
-       st8     [_tmp]=r18,0x08
-
-/*
- * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec)
- * (p6) is executed if we never entered virtual mode (TLB error)
- * (p7) is executed if we entered virtual mode as expected (normal case)
- *     1. GR8 = OS_MCA return status
- *     2. GR9 = SAL GP (physical)
- *     3. GR10 = 0/1 returning same/new context
- *     4. GR22 = New min state save area pointer
- *     returns ptr to SAL rtn save loc in _tmp
- */
-#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp)      \
-       movl    _tmp=ia64_os_to_sal_handoff_state;;     \
-       DATA_VA_TO_PA(_tmp);;                           \
-       ld8     r8=[_tmp],0x08;;                        \
-       ld8     r9=[_tmp],0x08;;                        \
-       ld8     r10=[_tmp],0x08;;                       \
-       ld8     r22=[_tmp],0x08;;
-       // now _tmp is pointing to SAL rtn save location
-
-/*
- * COLD_BOOT_HANDOFF_STATE() sets ia64_mca_os_to_sal_state
- *     imots_os_status=IA64_MCA_COLD_BOOT
- *     imots_sal_gp=SAL GP
- *     imots_context=IA64_MCA_SAME_CONTEXT
- *     imots_new_min_state=Min state save area pointer
- *     imots_sal_check_ra=Return address to location within SAL_CHECK
- *
- */
-#define COLD_BOOT_HANDOFF_STATE(sal_to_os_handoff,os_to_sal_handoff,tmp)\
-       movl    tmp=IA64_MCA_COLD_BOOT;                                 \
-       movl    sal_to_os_handoff=__pa(ia64_sal_to_os_handoff_state);   \
-       movl    os_to_sal_handoff=__pa(ia64_os_to_sal_handoff_state);;  \
-       st8     [os_to_sal_handoff]=tmp,8;;                             \
-       ld8     tmp=[sal_to_os_handoff],48;;                            \
-       st8     [os_to_sal_handoff]=tmp,8;;                             \
-       movl    tmp=IA64_MCA_SAME_CONTEXT;;                             \
-       st8     [os_to_sal_handoff]=tmp,8;;                             \
-       ld8     tmp=[sal_to_os_handoff],-8;;                            \
-       st8     [os_to_sal_handoff]=tmp,8;;                             \
-       ld8     tmp=[sal_to_os_handoff];;                               \
-       st8     [os_to_sal_handoff]=tmp;;
+#include "entry.h"
 
 #define GET_IA64_MCA_DATA(reg)                                         \
        GET_THIS_PADDR(reg, ia64_mca_data)                              \
        ;;                                                              \
        ld8 reg=[reg]
 
-       .global ia64_os_mca_dispatch
-       .global ia64_os_mca_dispatch_end
-       .global ia64_sal_to_os_handoff_state
-       .global ia64_os_to_sal_handoff_state
        .global ia64_do_tlb_purge
+       .global ia64_os_mca_dispatch
+       .global ia64_os_init_dispatch_monarch
+       .global ia64_os_init_dispatch_slave
 
        .text
        .align 16
 
+//StartMain////////////////////////////////////////////////////////////////////
+
 /*
  * Just the TLB purge part is moved to a separate function
  * so we can re-use the code for cpu hotplug code as well
@@ -207,34 +137,31 @@ ia64_do_tlb_purge:
        br.sptk.many b1
        ;;
 
-ia64_os_mca_dispatch:
+//EndMain//////////////////////////////////////////////////////////////////////
+
+//StartMain////////////////////////////////////////////////////////////////////
 
+ia64_os_mca_dispatch:
        // Serialize all MCA processing
        mov     r3=1;;
        LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
 ia64_os_mca_spin:
-       xchg8   r4=[r2],r3;;
+       xchg4   r4=[r2],r3;;
        cmp.ne  p6,p0=r4,r0
 (p6)   br ia64_os_mca_spin
 
-       // Save the SAL to OS MCA handoff state as defined
-       // by SAL SPEC 3.0
-       // NOTE : The order in which the state gets saved
-       //        is dependent on the way the C-structure
-       //        for ia64_mca_sal_to_os_state_t has been
-       //        defined in include/asm/mca.h
-       SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
-       ;;
-
-       // LOG PROCESSOR STATE INFO FROM HERE ON..
-begin_os_mca_dump:
-       br      ia64_os_mca_proc_state_dump;;
+       mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET    // use the MCA stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       mov r19=1                               // All MCA events are treated as monarch (for now)
+       br.sptk ia64_state_save                 // save the state that is not in minstate
+1:
 
-ia64_os_mca_done_dump:
-
-       LOAD_PHYSICAL(p0,r16,ia64_sal_to_os_handoff_state+56)
+       GET_IA64_MCA_DATA(r2)
+       // Using MCA stack, struct ia64_sal_os_state, variable proc_state_param
+       ;;
+       add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2
        ;;
-       ld8 r18=[r16]           // Get processor state parameter on existing PALE_CHECK.
+       ld8 r18=[r3]                            // Get processor state parameter on existing PALE_CHECK.
        ;;
        tbit.nz p6,p7=r18,60
 (p7)   br.spnt done_tlb_purge_and_reload
@@ -323,624 +250,775 @@ ia64_reload_tr:
        itr.d dtr[r20]=r16
        ;;
        srlz.d
-       ;;
-       br.sptk.many done_tlb_purge_and_reload
-err:
-       COLD_BOOT_HANDOFF_STATE(r20,r21,r22)
-       br.sptk.many ia64_os_mca_done_restore
 
 done_tlb_purge_and_reload:
 
-       // Setup new stack frame for OS_MCA handling
-       GET_IA64_MCA_DATA(r2)
-       ;;
-       add r3 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2
-       add r2 = IA64_MCA_CPU_RBSTORE_OFFSET, r2
-       ;;
-       rse_switch_context(r6,r3,r2);;  // RSC management in this new context
+       // switch to per cpu MCA stack
+       mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET    // use the MCA stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_new_stack
+1:
+
+       // everything saved, now we can set the kernel registers
+       mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET    // use the MCA stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_set_kernel_registers
+1:
 
+       // This must be done in physical mode
        GET_IA64_MCA_DATA(r2)
        ;;
-       add r2 = IA64_MCA_CPU_STACK_OFFSET+IA64_MCA_STACK_SIZE-16, r2
-       ;;
-       mov r12=r2              // establish new stack-pointer
+       mov r7=r2
 
         // Enter virtual mode from physical mode
        VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
-ia64_os_mca_virtual_begin:
+
+       // This code returns to SAL via SOS r2, in general SAL has no unwind
+       // data.  To get a clean termination when backtracing the C MCA/INIT
+       // handler, set a dummy return address of 0 in this routine.  That
+       // requires that ia64_os_mca_virtual_begin be a global function.
+ENTRY(ia64_os_mca_virtual_begin)
+       .prologue
+       .save rp,r0
+       .body
+
+       mov ar.rsc=3                            // set eager mode for C handler
+       mov r2=r7                               // see GET_IA64_MCA_DATA above
+       ;;
 
        // Call virtual mode handler
-       movl            r2=ia64_mca_ucmc_handler;;
-       mov             b6=r2;;
-       br.call.sptk.many    b0=b6;;
-.ret0:
+       alloc r14=ar.pfs,0,0,3,0
+       ;;
+       DATA_PA_TO_VA(r2,r7)
+       ;;
+       add out0=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2
+       add out1=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2
+       add out2=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET, r2
+       br.call.sptk.many    b0=ia64_mca_handler
+
        // Revert back to physical mode before going back to SAL
        PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
 ia64_os_mca_virtual_end:
 
-       // restore the original stack frame here
+END(ia64_os_mca_virtual_begin)
+
+       // switch back to previous stack
+       alloc r14=ar.pfs,0,0,0,0                // remove the MCA handler frame
+       mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET    // use the MCA stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_old_stack
+1:
+
+       mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET    // use the MCA stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_state_restore              // restore the SAL state
+1:
+
+       mov             b0=r12                  // SAL_CHECK return address
+
+       // release lock
+       LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);;
+       st4.rel         [r3]=r0
+
+       br              b0
+
+//EndMain//////////////////////////////////////////////////////////////////////
+
+//StartMain////////////////////////////////////////////////////////////////////
+
+//
+// SAL to OS entry point for INIT on all processors.  This has been defined for
+// registration purposes with SAL as a part of ia64_mca_init.  Monarch and
+// slave INIT have identical processing, except for the value of the
+// sos->monarch flag in r19.
+//
+
+ia64_os_init_dispatch_monarch:
+       mov r19=1                               // Bow, bow, ye lower middle classes!
+       br.sptk ia64_os_init_dispatch
+
+ia64_os_init_dispatch_slave:
+       mov r19=0                               // <igor>yeth, mathter</igor>
+
+ia64_os_init_dispatch:
+
+       mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET   // use the INIT stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_state_save                 // save the state that is not in minstate
+1:
+
+       // switch to per cpu INIT stack
+       mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET   // use the INIT stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_new_stack
+1:
+
+       // everything saved, now we can set the kernel registers
+       mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET   // use the INIT stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_set_kernel_registers
+1:
+
+       // This must be done in physical mode
        GET_IA64_MCA_DATA(r2)
        ;;
-       add r2 = IA64_MCA_CPU_STACKFRAME_OFFSET, r2
-       ;;
-       movl    r4=IA64_PSR_MC
+       mov r7=r2
+
+        // Enter virtual mode from physical mode
+       VIRTUAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_begin, r4)
+
+       // This code returns to SAL via SOS r2, in general SAL has no unwind
+       // data.  To get a clean termination when backtracing the C MCA/INIT
+       // handler, set a dummy return address of 0 in this routine.  That
+       // requires that ia64_os_init_virtual_begin be a global function.
+ENTRY(ia64_os_init_virtual_begin)
+       .prologue
+       .save rp,r0
+       .body
+
+       mov ar.rsc=3                            // set eager mode for C handler
+       mov r2=r7                               // see GET_IA64_MCA_DATA above
        ;;
-       rse_return_context(r4,r3,r2)    // switch from interrupt context for RSE
 
-       // let us restore all the registers from our PSI structure
-       mov     r8=gp
+       // Call virtual mode handler
+       alloc r14=ar.pfs,0,0,3,0
+       ;;
+       DATA_PA_TO_VA(r2,r7)
        ;;
-begin_os_mca_restore:
-       br      ia64_os_mca_proc_state_restore;;
+       add out0=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_PT_REGS_OFFSET, r2
+       add out1=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SWITCH_STACK_OFFSET, r2
+       add out2=IA64_MCA_CPU_INIT_STACK_OFFSET+MCA_SOS_OFFSET, r2
+       br.call.sptk.many    b0=ia64_init_handler
 
-ia64_os_mca_done_restore:
-       OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2);;
-       // branch back to SALE_CHECK
-       ld8             r3=[r2];;
-       mov             b0=r3;;         // SAL_CHECK return address
+       // Revert back to physical mode before going back to SAL
+       PHYSICAL_MODE_ENTER(r2, r3, ia64_os_init_virtual_end, r4)
+ia64_os_init_virtual_end:
 
-       // release lock
-       movl            r3=ia64_mca_serialize;;
-       DATA_VA_TO_PA(r3);;
-       st8.rel         [r3]=r0
+END(ia64_os_init_virtual_begin)
+
+       mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET   // use the INIT stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_state_restore              // restore the SAL state
+1:
 
+       // switch back to previous stack
+       alloc r14=ar.pfs,0,0,0,0                // remove the INIT handler frame
+       mov r3=IA64_MCA_CPU_INIT_STACK_OFFSET   // use the INIT stack
+       LOAD_PHYSICAL(p0,r2,1f)                 // return address
+       br.sptk ia64_old_stack
+1:
+
+       mov             b0=r12                  // SAL_CHECK return address
        br              b0
-       ;;
-ia64_os_mca_dispatch_end:
+
 //EndMain//////////////////////////////////////////////////////////////////////
 
+// common defines for the stubs
+#define        ms              r4
+#define        regs            r5
+#define        temp1           r2      /* careful, it overlaps with input registers */
+#define        temp2           r3      /* careful, it overlaps with input registers */
+#define        temp3           r7
+#define        temp4           r14
+
 
 //++
 // Name:
-//      ia64_os_mca_proc_state_dump()
+//     ia64_state_save()
 //
 // Stub Description:
 //
-//       This stub dumps the processor state during MCHK to a data area
+//     Save the state that is not in minstate.  This is sensitive to the layout of
+//     struct ia64_sal_os_state in mca.h.
+//
+//     r2 contains the return address, r3 contains either
+//     IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
+//
+//     The OS to SAL section of struct ia64_sal_os_state is set to a default
+//     value of cold boot (MCA) or warm boot (INIT) and return to the same
+//     context.  ia64_sal_os_state is also used to hold some registers that
+//     need to be saved and restored across the stack switches.
+//
+//     Most input registers to this stub come from PAL/SAL
+//     r1  os gp, physical
+//     r8  pal_proc entry point
+//     r9  sal_proc entry point
+//     r10 sal gp
+//     r11 MCA - rendevzous state, INIT - reason code
+//     r12 sal return address
+//     r17 pal min_state
+//     r18 processor state parameter
+//     r19 monarch flag, set by the caller of this routine
+//
+//     In addition to the SAL to OS state, this routine saves all the
+//     registers that appear in struct pt_regs and struct switch_stack,
+//     excluding those that are already in the PAL minstate area.  This
+//     results in a partial pt_regs and switch_stack, the C code copies the
+//     remaining registers from PAL minstate to pt_regs and switch_stack.  The
+//     resulting structures contain all the state of the original process when
+//     MCA/INIT occurred.
 //
 //--
 
-ia64_os_mca_proc_state_dump:
-// Save bank 1 GRs 16-31 which will be used by c-language code when we switch
-//  to virtual addressing mode.
-       GET_IA64_MCA_DATA(r2)
+ia64_state_save:
+       add regs=MCA_SOS_OFFSET, r3
+       add ms=MCA_SOS_OFFSET+8, r3
+       mov b0=r2               // save return address
+       cmp.eq p1,p2=IA64_MCA_CPU_MCA_STACK_OFFSET, r3
+       ;;
+       GET_IA64_MCA_DATA(temp2)
+       ;;
+       add temp1=temp2, regs   // struct ia64_sal_os_state on MCA or INIT stack
+       add temp2=temp2, ms     // struct ia64_sal_os_state+8 on MCA or INIT stack
+       ;;
+       mov regs=temp1          // save the start of sos
+       st8 [temp1]=r1,16       // os_gp
+       st8 [temp2]=r8,16       // pal_proc
+       ;;
+       st8 [temp1]=r9,16       // sal_proc
+       st8 [temp2]=r11,16      // rv_rc
+       mov r11=cr.iipa
+       ;;
+       st8 [temp1]=r18,16      // proc_state_param
+       st8 [temp2]=r19,16      // monarch
+       mov r6=IA64_KR(CURRENT)
+       ;;
+       st8 [temp1]=r12,16      // sal_ra
+       st8 [temp2]=r10,16      // sal_gp
+       mov r12=cr.isr
+       ;;
+       st8 [temp1]=r17,16      // pal_min_state
+       st8 [temp2]=r6,16       // prev_IA64_KR_CURRENT
+       mov r6=cr.ifa
+       ;;
+       st8 [temp1]=r0,16       // prev_task, starts off as NULL
+       st8 [temp2]=r12,16      // cr.isr
+       mov r12=cr.itir
+       ;;
+       st8 [temp1]=r6,16       // cr.ifa
+       st8 [temp2]=r12,16      // cr.itir
+       mov r12=cr.iim
+       ;;
+       st8 [temp1]=r11,16      // cr.iipa
+       st8 [temp2]=r12,16      // cr.iim
+       mov r6=cr.iha
+(p1)   mov r12=IA64_MCA_COLD_BOOT
+(p2)   mov r12=IA64_INIT_WARM_BOOT
+       ;;
+       st8 [temp1]=r6,16       // cr.iha
+       st8 [temp2]=r12         // os_status, default is cold boot
+       mov r6=IA64_MCA_SAME_CONTEXT
+       ;;
+       st8 [temp1]=r6          // context, default is same context
+
+       // Save the pt_regs data that is not in minstate.  The previous code
+       // left regs at sos.
+       add regs=MCA_PT_REGS_OFFSET-MCA_SOS_OFFSET, regs
+       ;;
+       add temp1=PT(B6), regs
+       mov temp3=b6
+       mov temp4=b7
+       add temp2=PT(B7), regs
+       ;;
+       st8 [temp1]=temp3,PT(AR_CSD)-PT(B6)             // save b6
+       st8 [temp2]=temp4,PT(AR_SSD)-PT(B7)             // save b7
+       mov temp3=ar.csd
+       mov temp4=ar.ssd
+       cover                                           // must be last in group
        ;;
-       add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2
-       ;;
-// save ar.NaT
-       mov             r5=ar.unat                  // ar.unat
-
-// save banked GRs 16-31 along with NaT bits
-       bsw.1;;
-       st8.spill       [r2]=r16,8;;
-       st8.spill       [r2]=r17,8;;
-       st8.spill       [r2]=r18,8;;
-       st8.spill       [r2]=r19,8;;
-       st8.spill       [r2]=r20,8;;
-       st8.spill       [r2]=r21,8;;
-       st8.spill       [r2]=r22,8;;
-       st8.spill       [r2]=r23,8;;
-       st8.spill       [r2]=r24,8;;
-       st8.spill       [r2]=r25,8;;
-       st8.spill       [r2]=r26,8;;
-       st8.spill       [r2]=r27,8;;
-       st8.spill       [r2]=r28,8;;
-       st8.spill       [r2]=r29,8;;
-       st8.spill       [r2]=r30,8;;
-       st8.spill       [r2]=r31,8;;
-
-       mov             r4=ar.unat;;
-       st8             [r2]=r4,8                // save User NaT bits for r16-r31
-       mov             ar.unat=r5                  // restore original unat
-       bsw.0;;
-
-//save BRs
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2                // duplicate r2 in r4
-
-       mov             r3=b0
-       mov             r5=b1
-       mov             r7=b2;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=b3
-       mov             r5=b4
-       mov             r7=b5;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=b6
-       mov             r5=b7;;
-       st8             [r2]=r3,2*8
-       st8             [r4]=r5,2*8;;
-
-cSaveCRs:
-// save CRs
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2                // duplicate r2 in r4
-
-       mov             r3=cr.dcr
-       mov             r5=cr.itm
-       mov             r7=cr.iva;;
-
-       st8             [r2]=r3,8*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;            // 48 byte rements
-
-       mov             r3=cr.pta;;
-       st8             [r2]=r3,8*8;;            // 64 byte rements
-
-// if PSR.ic=0, reading interruption registers causes an illegal operation fault
-       mov             r3=psr;;
-       tbit.nz.unc     p6,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
-(p6)    st8     [r2]=r0,9*8+160             // increment by 232 byte inc.
-begin_skip_intr_regs:
-(p6)   br              SkipIntrRegs;;
-
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2                // duplicate r2 in r6
-
-       mov             r3=cr.ipsr
-       mov             r5=cr.isr
-       mov             r7=r0;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=cr.iip
-       mov             r5=cr.ifa
-       mov             r7=cr.itir;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=cr.iipa
-       mov             r5=cr.ifs
-       mov             r7=cr.iim;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=cr25;;                   // cr.iha
-       st8             [r2]=r3,160;;               // 160 byte rement
-
-SkipIntrRegs:
-       st8             [r2]=r0,152;;               // another 152 byte .
-
-       add             r4=8,r2                     // duplicate r2 in r4
-       add             r6=2*8,r2                   // duplicate r2 in r6
-
-       mov             r3=cr.lid
-//     mov             r5=cr.ivr                     // cr.ivr, don't read it
-       mov             r7=cr.tpr;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=r0                       // cr.eoi => cr67
-       mov             r5=r0                       // cr.irr0 => cr68
-       mov             r7=r0;;                     // cr.irr1 => cr69
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=r0                       // cr.irr2 => cr70
-       mov             r5=r0                       // cr.irr3 => cr71
-       mov             r7=cr.itv;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=cr.pmv
-       mov             r5=cr.cmcv;;
-       st8             [r2]=r3,7*8
-       st8             [r4]=r5,7*8;;
-
-       mov             r3=r0                       // cr.lrr0 => cr80
-       mov             r5=r0;;                     // cr.lrr1 => cr81
-       st8             [r2]=r3,23*8
-       st8             [r4]=r5,23*8;;
-
-       adds            r2=25*8,r2;;
-
-cSaveARs:
-// save ARs
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2                // duplicate r2 in r6
-
-       mov             r3=ar.k0
-       mov             r5=ar.k1
-       mov             r7=ar.k2;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=ar.k3
-       mov             r5=ar.k4
-       mov             r7=ar.k5;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=ar.k6
-       mov             r5=ar.k7
-       mov             r7=r0;;                     // ar.kr8
-       st8             [r2]=r3,10*8
-       st8             [r4]=r5,10*8
-       st8             [r6]=r7,10*8;;           // rement by 72 bytes
-
-       mov             r3=ar.rsc
-       mov             ar.rsc=r0                           // put RSE in enforced lazy mode
-       mov             r5=ar.bsp
-       ;;
-       mov             r7=ar.bspstore;;
-       st8             [r2]=r3,3*8
-       st8             [r4]=r5,3*8
-       st8             [r6]=r7,3*8;;
-
-       mov             r3=ar.rnat;;
-       st8             [r2]=r3,8*13             // increment by 13x8 bytes
-
-       mov             r3=ar.ccv;;
-       st8             [r2]=r3,8*4
-
-       mov             r3=ar.unat;;
-       st8             [r2]=r3,8*4
-
-       mov             r3=ar.fpsr;;
-       st8             [r2]=r3,8*4
-
-       mov             r3=ar.itc;;
-       st8             [r2]=r3,160                 // 160
-
-       mov             r3=ar.pfs;;
-       st8             [r2]=r3,8
-
-       mov             r3=ar.lc;;
-       st8             [r2]=r3,8
-
-       mov             r3=ar.ec;;
-       st8             [r2]=r3
-       add             r2=8*62,r2               //padding
-
-// save RRs
-       mov             ar.lc=0x08-1
-       movl            r4=0x00;;
-
-cStRR:
-       dep.z           r5=r4,61,3;;
-       mov             r3=rr[r5];;
-       st8             [r2]=r3,8
-       add             r4=1,r4
-       br.cloop.sptk.few       cStRR
-       ;;
-end_os_mca_dump:
-       br      ia64_os_mca_done_dump;;
+       st8 [temp1]=temp3,PT(AR_UNAT)-PT(AR_CSD)        // save ar.csd
+       st8 [temp2]=temp4,PT(AR_PFS)-PT(AR_SSD)         // save ar.ssd
+       mov temp3=ar.unat
+       mov temp4=ar.pfs
+       ;;
+       st8 [temp1]=temp3,PT(AR_RNAT)-PT(AR_UNAT)       // save ar.unat
+       st8 [temp2]=temp4,PT(AR_BSPSTORE)-PT(AR_PFS)    // save ar.pfs
+       mov temp3=ar.rnat
+       mov temp4=ar.bspstore
+       ;;
+       st8 [temp1]=temp3,PT(LOADRS)-PT(AR_RNAT)        // save ar.rnat
+       st8 [temp2]=temp4,PT(AR_FPSR)-PT(AR_BSPSTORE)   // save ar.bspstore
+       mov temp3=ar.bsp
+       ;;
+       sub temp3=temp3, temp4  // ar.bsp - ar.bspstore
+       mov temp4=ar.fpsr
+       ;;
+       shl temp3=temp3,16      // compute ar.rsc to be used for "loadrs"
+       ;;
+       st8 [temp1]=temp3,PT(AR_CCV)-PT(LOADRS)         // save loadrs
+       st8 [temp2]=temp4,PT(F6)-PT(AR_FPSR)            // save ar.fpsr
+       mov temp3=ar.ccv
+       ;;
+       st8 [temp1]=temp3,PT(F7)-PT(AR_CCV)             // save ar.ccv
+       stf.spill [temp2]=f6,PT(F8)-PT(F6)
+       ;;
+       stf.spill [temp1]=f7,PT(F9)-PT(F7)
+       stf.spill [temp2]=f8,PT(F10)-PT(F8)
+       ;;
+       stf.spill [temp1]=f9,PT(F11)-PT(F9)
+       stf.spill [temp2]=f10
+       ;;
+       stf.spill [temp1]=f11
+
+       // Save the switch_stack data that is not in minstate nor pt_regs.  The
+       // previous code left regs at pt_regs.
+       add regs=MCA_SWITCH_STACK_OFFSET-MCA_PT_REGS_OFFSET, regs
+       ;;
+       add temp1=SW(F2), regs
+       add temp2=SW(F3), regs
+       ;;
+       stf.spill [temp1]=f2,32
+       stf.spill [temp2]=f3,32
+       ;;
+       stf.spill [temp1]=f4,32
+       stf.spill [temp2]=f5,32
+       ;;
+       stf.spill [temp1]=f12,32
+       stf.spill [temp2]=f13,32
+       ;;
+       stf.spill [temp1]=f14,32
+       stf.spill [temp2]=f15,32
+       ;;
+       stf.spill [temp1]=f16,32
+       stf.spill [temp2]=f17,32
+       ;;
+       stf.spill [temp1]=f18,32
+       stf.spill [temp2]=f19,32
+       ;;
+       stf.spill [temp1]=f20,32
+       stf.spill [temp2]=f21,32
+       ;;
+       stf.spill [temp1]=f22,32
+       stf.spill [temp2]=f23,32
+       ;;
+       stf.spill [temp1]=f24,32
+       stf.spill [temp2]=f25,32
+       ;;
+       stf.spill [temp1]=f26,32
+       stf.spill [temp2]=f27,32
+       ;;
+       stf.spill [temp1]=f28,32
+       stf.spill [temp2]=f29,32
+       ;;
+       stf.spill [temp1]=f30,SW(B2)-SW(F30)
+       stf.spill [temp2]=f31,SW(B3)-SW(F31)
+       mov temp3=b2
+       mov temp4=b3
+       ;;
+       st8 [temp1]=temp3,16    // save b2
+       st8 [temp2]=temp4,16    // save b3
+       mov temp3=b4
+       mov temp4=b5
+       ;;
+       st8 [temp1]=temp3,SW(AR_LC)-SW(B4)      // save b4
+       st8 [temp2]=temp4       // save b5
+       mov temp3=ar.lc
+       ;;
+       st8 [temp1]=temp3       // save ar.lc
+
+       // FIXME: Some proms are incorrectly accessing the minstate area as
+       // cached data.  The C code uses region 6, uncached virtual.  Ensure
+       // that there is no cache data lying around for the first 1K of the
+       // minstate area.
+       // Remove this code in September 2006, that gives platforms a year to
+       // fix their proms and get their customers updated.
+
+       add r1=32*1,r17
+       add r2=32*2,r17
+       add r3=32*3,r17
+       add r4=32*4,r17
+       add r5=32*5,r17
+       add r6=32*6,r17
+       add r7=32*7,r17
+       ;;
+       fc r17
+       fc r1
+       fc r2
+       fc r3
+       fc r4
+       fc r5
+       fc r6
+       fc r7
+       add r17=32*8,r17
+       add r1=32*8,r1
+       add r2=32*8,r2
+       add r3=32*8,r3
+       add r4=32*8,r4
+       add r5=32*8,r5
+       add r6=32*8,r6
+       add r7=32*8,r7
+       ;;
+       fc r17
+       fc r1
+       fc r2
+       fc r3
+       fc r4
+       fc r5
+       fc r6
+       fc r7
+       add r17=32*8,r17
+       add r1=32*8,r1
+       add r2=32*8,r2
+       add r3=32*8,r3
+       add r4=32*8,r4
+       add r5=32*8,r5
+       add r6=32*8,r6
+       add r7=32*8,r7
+       ;;
+       fc r17
+       fc r1
+       fc r2
+       fc r3
+       fc r4
+       fc r5
+       fc r6
+       fc r7
+       add r17=32*8,r17
+       add r1=32*8,r1
+       add r2=32*8,r2
+       add r3=32*8,r3
+       add r4=32*8,r4
+       add r5=32*8,r5
+       add r6=32*8,r6
+       add r7=32*8,r7
+       ;;
+       fc r17
+       fc r1
+       fc r2
+       fc r3
+       fc r4
+       fc r5
+       fc r6
+       fc r7
+
+       br.sptk b0
 
 //EndStub//////////////////////////////////////////////////////////////////////
 
 
 //++
 // Name:
-//       ia64_os_mca_proc_state_restore()
+//     ia64_state_restore()
 //
 // Stub Description:
 //
-//       This is a stub to restore the saved processor state during MCHK
+//     Restore the SAL/OS state.  This is sensitive to the layout of struct
+//     ia64_sal_os_state in mca.h.
+//
+//     r2 contains the return address, r3 contains either
+//     IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
+//
+//     In addition to the SAL to OS state, this routine restores all the
+//     registers that appear in struct pt_regs and struct switch_stack,
+//     excluding those in the PAL minstate area.
 //
 //--
 
-ia64_os_mca_proc_state_restore:
+ia64_state_restore:
+       // Restore the switch_stack data that is not in minstate nor pt_regs.
+       add regs=MCA_SWITCH_STACK_OFFSET, r3
+       mov b0=r2               // save return address
+       ;;
+       GET_IA64_MCA_DATA(temp2)
+       ;;
+       add regs=temp2, regs
+       ;;
+       add temp1=SW(F2), regs
+       add temp2=SW(F3), regs
+       ;;
+       ldf.fill f2=[temp1],32
+       ldf.fill f3=[temp2],32
+       ;;
+       ldf.fill f4=[temp1],32
+       ldf.fill f5=[temp2],32
+       ;;
+       ldf.fill f12=[temp1],32
+       ldf.fill f13=[temp2],32
+       ;;
+       ldf.fill f14=[temp1],32
+       ldf.fill f15=[temp2],32
+       ;;
+       ldf.fill f16=[temp1],32
+       ldf.fill f17=[temp2],32
+       ;;
+       ldf.fill f18=[temp1],32
+       ldf.fill f19=[temp2],32
+       ;;
+       ldf.fill f20=[temp1],32
+       ldf.fill f21=[temp2],32
+       ;;
+       ldf.fill f22=[temp1],32
+       ldf.fill f23=[temp2],32
+       ;;
+       ldf.fill f24=[temp1],32
+       ldf.fill f25=[temp2],32
+       ;;
+       ldf.fill f26=[temp1],32
+       ldf.fill f27=[temp2],32
+       ;;
+       ldf.fill f28=[temp1],32
+       ldf.fill f29=[temp2],32
+       ;;
+       ldf.fill f30=[temp1],SW(B2)-SW(F30)
+       ldf.fill f31=[temp2],SW(B3)-SW(F31)
+       ;;
+       ld8 temp3=[temp1],16    // restore b2
+       ld8 temp4=[temp2],16    // restore b3
+       ;;
+       mov b2=temp3
+       mov b3=temp4
+       ld8 temp3=[temp1],SW(AR_LC)-SW(B4)      // restore b4
+       ld8 temp4=[temp2]       // restore b5
+       ;;
+       mov b4=temp3
+       mov b5=temp4
+       ld8 temp3=[temp1]       // restore ar.lc
+       ;;
+       mov ar.lc=temp3
 
-// Restore bank1 GR16-31
-       GET_IA64_MCA_DATA(r2)
+       // Restore the pt_regs data that is not in minstate.  The previous code
+       // left regs at switch_stack.
+       add regs=MCA_PT_REGS_OFFSET-MCA_SWITCH_STACK_OFFSET, regs
+       ;;
+       add temp1=PT(B6), regs
+       add temp2=PT(B7), regs
+       ;;
+       ld8 temp3=[temp1],PT(AR_CSD)-PT(B6)             // restore b6
+       ld8 temp4=[temp2],PT(AR_SSD)-PT(B7)             // restore b7
+       ;;
+       mov b6=temp3
+       mov b7=temp4
+       ld8 temp3=[temp1],PT(AR_UNAT)-PT(AR_CSD)        // restore ar.csd
+       ld8 temp4=[temp2],PT(AR_PFS)-PT(AR_SSD)         // restore ar.ssd
+       ;;
+       mov ar.csd=temp3
+       mov ar.ssd=temp4
+       ld8 temp3=[temp1]                               // restore ar.unat
+       add temp1=PT(AR_CCV)-PT(AR_UNAT), temp1
+       ld8 temp4=[temp2],PT(AR_FPSR)-PT(AR_PFS)        // restore ar.pfs
+       ;;
+       mov ar.unat=temp3
+       mov ar.pfs=temp4
+       // ar.rnat, ar.bspstore, loadrs are restore in ia64_old_stack.
+       ld8 temp3=[temp1],PT(F6)-PT(AR_CCV)             // restore ar.ccv
+       ld8 temp4=[temp2],PT(F7)-PT(AR_FPSR)            // restore ar.fpsr
+       ;;
+       mov ar.ccv=temp3
+       mov ar.fpsr=temp4
+       ldf.fill f6=[temp1],PT(F8)-PT(F6)
+       ldf.fill f7=[temp2],PT(F9)-PT(F7)
+       ;;
+       ldf.fill f8=[temp1],PT(F10)-PT(F8)
+       ldf.fill f9=[temp2],PT(F11)-PT(F9)
+       ;;
+       ldf.fill f10=[temp1]
+       ldf.fill f11=[temp2]
+
+       // Restore the SAL to OS state. The previous code left regs at pt_regs.
+       add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs
        ;;
-       add r2 = IA64_MCA_CPU_PROC_STATE_DUMP_OFFSET, r2
-
-restore_GRs:                                    // restore bank-1 GRs 16-31
-       bsw.1;;
-       add             r3=16*8,r2;;                // to get to NaT of GR 16-31
-       ld8             r3=[r3];;
-       mov             ar.unat=r3;;                // first restore NaT
-
-       ld8.fill        r16=[r2],8;;
-       ld8.fill        r17=[r2],8;;
-       ld8.fill        r18=[r2],8;;
-       ld8.fill        r19=[r2],8;;
-       ld8.fill        r20=[r2],8;;
-       ld8.fill        r21=[r2],8;;
-       ld8.fill        r22=[r2],8;;
-       ld8.fill        r23=[r2],8;;
-       ld8.fill        r24=[r2],8;;
-       ld8.fill        r25=[r2],8;;
-       ld8.fill        r26=[r2],8;;
-       ld8.fill        r27=[r2],8;;
-       ld8.fill        r28=[r2],8;;
-       ld8.fill        r29=[r2],8;;
-       ld8.fill        r30=[r2],8;;
-       ld8.fill        r31=[r2],8;;
-
-       ld8             r3=[r2],8;;              // increment to skip NaT
-       bsw.0;;
-
-restore_BRs:
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2;;              // duplicate r2 in r4
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             b0=r3
-       mov             b1=r5
-       mov             b2=r7;;
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             b3=r3
-       mov             b4=r5
-       mov             b5=r7;;
-
-       ld8             r3=[r2],2*8
-       ld8             r5=[r4],2*8;;
-       mov             b6=r3
-       mov             b7=r5;;
-
-restore_CRs:
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2;;              // duplicate r2 in r4
-
-       ld8             r3=[r2],8*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;            // 48 byte increments
-       mov             cr.dcr=r3
-       mov             cr.itm=r5
-       mov             cr.iva=r7;;
-
-       ld8             r3=[r2],8*8;;            // 64 byte increments
-//      mov            cr.pta=r3
-
-
-// if PSR.ic=1, reading interruption registers causes an illegal operation fault
-       mov             r3=psr;;
-       tbit.nz.unc     p6,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
-(p6)    st8     [r2]=r0,9*8+160             // increment by 232 byte inc.
-
-begin_rskip_intr_regs:
-(p6)   br              rSkipIntrRegs;;
-
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2;;              // duplicate r2 in r4
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             cr.ipsr=r3
-//     mov             cr.isr=r5                   // cr.isr is read only
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             cr.iip=r3
-       mov             cr.ifa=r5
-       mov             cr.itir=r7;;
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             cr.iipa=r3
-       mov             cr.ifs=r5
-       mov             cr.iim=r7
-
-       ld8             r3=[r2],160;;               // 160 byte increment
-       mov             cr.iha=r3
-
-rSkipIntrRegs:
-       ld8             r3=[r2],152;;               // another 152 byte inc.
-
-       add             r4=8,r2                     // duplicate r2 in r4
-       add             r6=2*8,r2;;                 // duplicate r2 in r6
-
-       ld8             r3=[r2],8*3
-       ld8             r5=[r4],8*3
-       ld8             r7=[r6],8*3;;
-       mov             cr.lid=r3
-//     mov             cr.ivr=r5                   // cr.ivr is read only
-       mov             cr.tpr=r7;;
-
-       ld8             r3=[r2],8*3
-       ld8             r5=[r4],8*3
-       ld8             r7=[r6],8*3;;
-//     mov             cr.eoi=r3
-//     mov             cr.irr0=r5                  // cr.irr0 is read only
-//     mov             cr.irr1=r7;;                // cr.irr1 is read only
-
-       ld8             r3=[r2],8*3
-       ld8             r5=[r4],8*3
-       ld8             r7=[r6],8*3;;
-//     mov             cr.irr2=r3                  // cr.irr2 is read only
-//     mov             cr.irr3=r5                  // cr.irr3 is read only
-       mov             cr.itv=r7;;
-
-       ld8             r3=[r2],8*7
-       ld8             r5=[r4],8*7;;
-       mov             cr.pmv=r3
-       mov             cr.cmcv=r5;;
-
-       ld8             r3=[r2],8*23
-       ld8             r5=[r4],8*23;;
-       adds            r2=8*23,r2
-       adds            r4=8*23,r4;;
-//     mov             cr.lrr0=r3
-//     mov             cr.lrr1=r5
-
-       adds            r2=8*2,r2;;
-
-restore_ARs:
-       add             r4=8,r2                  // duplicate r2 in r4
-       add             r6=2*8,r2;;              // duplicate r2 in r4
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             ar.k0=r3
-       mov             ar.k1=r5
-       mov             ar.k2=r7;;
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-       mov             ar.k3=r3
-       mov             ar.k4=r5
-       mov             ar.k5=r7;;
-
-       ld8             r3=[r2],10*8
-       ld8             r5=[r4],10*8
-       ld8             r7=[r6],10*8;;
-       mov             ar.k6=r3
-       mov             ar.k7=r5
-       ;;
-
-       ld8             r3=[r2],3*8
-       ld8             r5=[r4],3*8
-       ld8             r7=[r6],3*8;;
-//     mov             ar.rsc=r3
-//     mov             ar.bsp=r5                   // ar.bsp is read only
-       mov             ar.rsc=r0                           // make sure that RSE is in enforced lazy mode
-       ;;
-       mov             ar.bspstore=r7;;
-
-       ld8             r9=[r2],8*13;;
-       mov             ar.rnat=r9
-
-       mov             ar.rsc=r3
-       ld8             r3=[r2],8*4;;
-       mov             ar.ccv=r3
-
-       ld8             r3=[r2],8*4;;
-       mov             ar.unat=r3
-
-       ld8             r3=[r2],8*4;;
-       mov             ar.fpsr=r3
-
-       ld8             r3=[r2],160;;               // 160
-//      mov            ar.itc=r3
-
-       ld8             r3=[r2],8;;
-       mov             ar.pfs=r3
-
-       ld8             r3=[r2],8;;
-       mov             ar.lc=r3
-
-       ld8             r3=[r2];;
-       mov             ar.ec=r3
-       add             r2=8*62,r2;;             // padding
-
-restore_RRs:
-       mov             r5=ar.lc
-       mov             ar.lc=0x08-1
-       movl            r4=0x00;;
-cStRRr:
-       dep.z           r7=r4,61,3
-       ld8             r3=[r2],8;;
-       mov             rr[r7]=r3                   // what are its access previledges?
-       add             r4=1,r4
-       br.cloop.sptk.few       cStRRr
-       ;;
-       mov             ar.lc=r5
-       ;;
-end_os_mca_restore:
-       br      ia64_os_mca_done_restore;;
+       add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs
+       add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs
+       ;;
+       ld8 r12=[temp1],16      // sal_ra
+       ld8 r9=[temp2],16       // sal_gp
+       ;;
+       ld8 r22=[temp1],24      // pal_min_state, virtual.  skip prev_task
+       ld8 r21=[temp2],16      // prev_IA64_KR_CURRENT
+       ;;
+       ld8 temp3=[temp1],16    // cr.isr
+       ld8 temp4=[temp2],16    // cr.ifa
+       ;;
+       mov cr.isr=temp3
+       mov cr.ifa=temp4
+       ld8 temp3=[temp1],16    // cr.itir
+       ld8 temp4=[temp2],16    // cr.iipa
+       ;;
+       mov cr.itir=temp3
+       mov cr.iipa=temp4
+       ld8 temp3=[temp1],16    // cr.iim
+       ld8 temp4=[temp2],16    // cr.iha
+       ;;
+       mov cr.iim=temp3
+       mov cr.iha=temp4
+       dep r22=0,r22,62,2      // pal_min_state, physical, uncached
+       mov IA64_KR(CURRENT)=r21
+       ld8 r8=[temp1]          // os_status
+       ld8 r10=[temp2]         // context
+
+       br.sptk b0
 
 //EndStub//////////////////////////////////////////////////////////////////////
 
 
-// ok, the issue here is that we need to save state information so
-// it can be useable by the kernel debugger and show regs routines.
-// In order to do this, our best bet is save the current state (plus
-// the state information obtain from the MIN_STATE_AREA) into a pt_regs
-// format.  This way we can pass it on in a useable format.
+//++
+// Name:
+//     ia64_new_stack()
 //
-
+// Stub Description:
 //
-// SAL to OS entry point for INIT on the monarch processor
-// This has been defined for registration purposes with SAL
-// as a part of ia64_mca_init.
+//     Switch to the MCA/INIT stack.
 //
-// When we get here, the following registers have been
-// set by the SAL for our use
+//     r2 contains the return address, r3 contains either
+//     IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
 //
-//             1. GR1 = OS INIT GP
-//             2. GR8 = PAL_PROC physical address
-//             3. GR9 = SAL_PROC physical address
-//             4. GR10 = SAL GP (physical)
-//             5. GR11 = Init Reason
-//                     0 = Received INIT for event other than crash dump switch
-//                     1 = Received wakeup at the end of an OS_MCA corrected machine check
-//                     2 = Received INIT dude to CrashDump switch assertion
+//     On entry RBS is still on the original stack, this routine switches RBS
+//     to use the MCA/INIT stack.
 //
-//             6. GR12 = Return address to location within SAL_INIT procedure
-
+//     On entry, sos->pal_min_state is physical, on exit it is virtual.
+//
+//--
 
-GLOBAL_ENTRY(ia64_monarch_init_handler)
-       .prologue
-       // stash the information the SAL passed to os
-       SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
+ia64_new_stack:
+       add regs=MCA_PT_REGS_OFFSET, r3
+       add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3
+       mov b0=r2                       // save return address
+       GET_IA64_MCA_DATA(temp1)
+       invala
        ;;
-       SAVE_MIN_WITH_COVER
+       add temp2=temp2, temp1          // struct ia64_sal_os_state.pal_min_state on MCA or INIT stack
+       add regs=regs, temp1            // struct pt_regs on MCA or INIT stack
        ;;
-       mov r8=cr.ifa
-       mov r9=cr.isr
-       adds r3=8,r2                            // set up second base pointer
+       // Address of minstate area provided by PAL is physical, uncacheable.
+       // Convert to Linux virtual address in region 6 for C code.
+       ld8 ms=[temp2]                  // pal_min_state, physical
        ;;
-       SAVE_REST
-
-// ok, enough should be saved at this point to be dangerous, and supply
-// information for a dump
-// We need to switch to Virtual mode before hitting the C functions.
+       dep temp1=-1,ms,62,2            // set region 6
+       mov temp3=IA64_RBS_OFFSET-MCA_PT_REGS_OFFSET
+       ;;
+       st8 [temp2]=temp1               // pal_min_state, virtual
 
-       movl    r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN
-       mov     r3=psr  // get the current psr, minimum enabled at this point
+       add temp4=temp3, regs           // start of bspstore on new stack
        ;;
-       or      r2=r2,r3
+       mov ar.bspstore=temp4           // switch RBS to MCA/INIT stack
        ;;
-       movl    r3=IVirtual_Switch
+       flushrs                         // must be first in group
+       br.sptk b0
+
+//EndStub//////////////////////////////////////////////////////////////////////
+
+
+//++
+// Name:
+//     ia64_old_stack()
+//
+// Stub Description:
+//
+//     Switch to the old stack.
+//
+//     r2 contains the return address, r3 contains either
+//     IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
+//
+//     On entry, pal_min_state is virtual, on exit it is physical.
+//
+//     On entry RBS is on the MCA/INIT stack, this routine switches RBS
+//     back to the previous stack.
+//
+//     The psr is set to all zeroes.  SAL return requires either all zeroes or
+//     just psr.mc set.  Leaving psr.mc off allows INIT to be issued if this
+//     code does not perform correctly.
+//
+//     The dirty registers at the time of the event were flushed to the
+//     MCA/INIT stack in ia64_pt_regs_save().  Restore the dirty registers
+//     before reverting to the previous bspstore.
+//--
+
+ia64_old_stack:
+       add regs=MCA_PT_REGS_OFFSET, r3
+       mov b0=r2                       // save return address
+       GET_IA64_MCA_DATA(temp2)
+       LOAD_PHYSICAL(p0,temp1,1f)
        ;;
-       mov     cr.iip=r3       // short return to set the appropriate bits
-       mov     cr.ipsr=r2      // need to do an rfi to set appropriate bits
+       mov cr.ipsr=r0
+       mov cr.ifs=r0
+       mov cr.iip=temp1
        ;;
+       invala
        rfi
+1:
+
+       add regs=regs, temp2            // struct pt_regs on MCA or INIT stack
        ;;
-IVirtual_Switch:
-       //
-       // We should now be running virtual
-       //
-       // Let's call the C handler to get the rest of the state info
-       //
-       alloc r14=ar.pfs,0,0,2,0                // now it's safe (must be first in insn group!)
+       add temp1=PT(LOADRS), regs
        ;;
-       adds out0=16,sp                         // out0 = pointer to pt_regs
+       ld8 temp2=[temp1],PT(AR_BSPSTORE)-PT(LOADRS)    // restore loadrs
        ;;
-       DO_SAVE_SWITCH_STACK
-       .body
-       adds out1=16,sp                         // out0 = pointer to switch_stack
+       ld8 temp3=[temp1],PT(AR_RNAT)-PT(AR_BSPSTORE)   // restore ar.bspstore
+       mov ar.rsc=temp2
+       ;;
+       loadrs
+       ld8 temp4=[temp1]               // restore ar.rnat
+       ;;
+       mov ar.bspstore=temp3           // back to old stack
+       ;;
+       mov ar.rnat=temp4
+       ;;
+
+       br.sptk b0
 
-       br.call.sptk.many rp=ia64_init_handler
-.ret1:
+//EndStub//////////////////////////////////////////////////////////////////////
 
-return_from_init:
-       br.sptk return_from_init
-END(ia64_monarch_init_handler)
 
+//++
+// Name:
+//     ia64_set_kernel_registers()
 //
-// SAL to OS entry point for INIT on the slave processor
-// This has been defined for registration purposes with SAL
-// as a part of ia64_mca_init.
+// Stub Description:
+//
+//     Set the registers that are required by the C code in order to run on an
+//     MCA/INIT stack.
+//
+//     r2 contains the return address, r3 contains either
+//     IA64_MCA_CPU_MCA_STACK_OFFSET or IA64_MCA_CPU_INIT_STACK_OFFSET.
 //
+//--
+
+ia64_set_kernel_registers:
+       add temp3=MCA_SP_OFFSET, r3
+       add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r3
+       mov b0=r2               // save return address
+       GET_IA64_MCA_DATA(temp1)
+       ;;
+       add temp4=temp4, temp1  // &struct ia64_sal_os_state.os_gp
+       add r12=temp1, temp3    // kernel stack pointer on MCA/INIT stack
+       add r13=temp1, r3       // set current to start of MCA/INIT stack
+       ;;
+       ld8 r1=[temp4]          // OS GP from SAL OS state
+       ;;
+       DATA_PA_TO_VA(r1,temp1)
+       DATA_PA_TO_VA(r12,temp2)
+       DATA_PA_TO_VA(r13,temp3)
+       ;;
+       mov IA64_KR(CURRENT)=r13
+
+       // FIXME: do I need to wire IA64_KR_CURRENT_STACK and IA64_TR_CURRENT_STACK?
+
+       br.sptk b0
+
+//EndStub//////////////////////////////////////////////////////////////////////
+
+#undef ms
+#undef regs
+#undef temp1
+#undef temp2
+#undef temp3
+#undef temp4
+
 
-GLOBAL_ENTRY(ia64_slave_init_handler)
-1:     br.sptk 1b
-END(ia64_slave_init_handler)
+// Support function for mca.c, it is here to avoid using inline asm.  Given the
+// address of an rnat slot, if that address is below the current ar.bspstore
+// then return the contents of that slot, otherwise return the contents of
+// ar.rnat.
+GLOBAL_ENTRY(ia64_get_rnat)
+       alloc r14=ar.pfs,1,0,0,0
+       mov ar.rsc=0
+       ;;
+       mov r14=ar.bspstore
+       ;;
+       cmp.lt p6,p7=in0,r14
+       ;;
+(p6)   ld8 r8=[in0]
+(p7)   mov r8=ar.rnat
+       mov ar.rsc=3
+       br.ret.sptk.many rp
+END(ia64_get_rnat)
index abc0113a821df8eee06fca411866cfe4de324a6d..6e683745af49d1ceb128fc99ec60b61ad76a61f6 100644 (file)
@@ -4,6 +4,8 @@
  *
  * Copyright (C) 2004 FUJITSU LIMITED
  * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com)
+ * Copyright (C) 2005 Silicon Graphics, Inc
+ * Copyright (C) 2005 Keith Owens <kaos@sgi.com>
  */
 #include <linux/config.h>
 #include <linux/types.h>
 /* max size of SAL error record (default) */
 static int sal_rec_max = 10000;
 
-/* from mca.c */
-static ia64_mca_sal_to_os_state_t *sal_to_os_handoff_state;
-static ia64_mca_os_to_sal_state_t *os_to_sal_handoff_state;
-
 /* from mca_drv_asm.S */
 extern void *mca_handler_bhhook(void);
 
@@ -316,7 +314,8 @@ init_record_index_pools(void)
  */
 
 static mca_type_t
-is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+             struct ia64_sal_os_state *sos)
 {
        pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
 
@@ -327,7 +326,7 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
         * Therefore it is local MCA when rendezvous has not been requested.
         * Failed to rendezvous, the system must be down.
         */
-       switch (sal_to_os_handoff_state->imsto_rendez_state) {
+       switch (sos->rv_rc) {
                case -1: /* SAL rendezvous unsuccessful */
                        return MCA_IS_GLOBAL;
                case  0: /* SAL rendezvous not required */
@@ -388,7 +387,8 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci)
  */
 
 static int
-recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+                       struct ia64_sal_os_state *sos)
 {
        sal_log_mod_error_info_t *smei;
        pal_min_state_area_t *pmsa;
@@ -426,7 +426,7 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
                         *  setup for resume to bottom half of MCA,
                         * "mca_handler_bhhook"
                         */
-                       pmsa = (pal_min_state_area_t *)(sal_to_os_handoff_state->pal_min_state | (6ul<<61));
+                       pmsa = sos->pal_min_state;
                        /* pass to bhhook as 1st argument (gr8) */
                        pmsa->pmsa_gr[8-1] = smei->target_identifier;
                        /* set interrupted return address (but no use) */
@@ -459,7 +459,8 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec
  */
 
 static int
-recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+                           struct ia64_sal_os_state *sos)
 {
        int status = 0;
        pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
@@ -469,7 +470,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
                case 1: /* partial read */
                case 3: /* full line(cpu) read */
                case 9: /* I/O space read */
-                       status = recover_from_read_error(slidx, peidx, pbci);
+                       status = recover_from_read_error(slidx, peidx, pbci, sos);
                        break;
                case 0: /* unknown */
                case 2: /* partial write */
@@ -508,7 +509,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_
  */
 
 static int
-recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci)
+recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci,
+                            struct ia64_sal_os_state *sos)
 {
        pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx);
 
@@ -545,7 +547,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
         * This means "there are some platform errors".
         */
        if (platform) 
-               return recover_from_platform_error(slidx, peidx, pbci);
+               return recover_from_platform_error(slidx, peidx, pbci, sos);
        /* 
         * On account of strange SAL error record, we cannot recover. 
         */
@@ -562,8 +564,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *
 
 static int
 mca_try_to_recover(void *rec, 
-       ia64_mca_sal_to_os_state_t *sal_to_os_state,
-       ia64_mca_os_to_sal_state_t *os_to_sal_state)
+       struct ia64_sal_os_state *sos)
 {
        int platform_err;
        int n_proc_err;
@@ -571,10 +572,6 @@ mca_try_to_recover(void *rec,
        peidx_table_t peidx;
        pal_bus_check_info_t pbci;
 
-       /* handoff state from/to mca.c */
-       sal_to_os_handoff_state = sal_to_os_state;
-       os_to_sal_handoff_state = os_to_sal_state;
-
        /* Make index of SAL error record */
        platform_err = mca_make_slidx(rec, &slidx);
 
@@ -597,11 +594,11 @@ mca_try_to_recover(void *rec,
        *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0);
 
        /* Check whether MCA is global or not */
-       if (is_mca_global(&peidx, &pbci))
+       if (is_mca_global(&peidx, &pbci, sos))
                return 0;
        
        /* Try to recover a processor error */
-       return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci);
+       return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos);
 }
 
 /*
index f6d8a010d99beacb04dc2d3a9cf8af2e14237a3e..85ed54179afa52585f74cbbd783764c0218a97eb 100644 (file)
@@ -4,73 +4,6 @@
 
 #include "entry.h"
 
-/*
- * For ivt.s we want to access the stack virtually so we don't have to disable translation
- * on interrupts.
- *
- *  On entry:
- *     r1:     pointer to current task (ar.k6)
- */
-#define MINSTATE_START_SAVE_MIN_VIRT                                                           \
-(pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
-       ;;                                                                                      \
-(pUStk)        mov.m r24=ar.rnat;                                                                      \
-(pUStk)        addl r22=IA64_RBS_OFFSET,r1;                    /* compute base of RBS */               \
-(pKStk) mov r1=sp;                                     /* get sp  */                           \
-       ;;                                                                                      \
-(pUStk) lfetch.fault.excl.nt1 [r22];                                                           \
-(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;   /* compute base of memory stack */      \
-(pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
-       ;;                                                                                      \
-(pUStk)        mov ar.bspstore=r22;                            /* switch to kernel RBS */              \
-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1;                 /* if in kernel mode, use sp (r12) */   \
-       ;;                                                                                      \
-(pUStk)        mov r18=ar.bsp;                                                                         \
-(pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */
-
-#define MINSTATE_END_SAVE_MIN_VIRT                                                             \
-       bsw.1;                  /* switch back to bank 1 (must be last in insn group) */        \
-       ;;
-
-/*
- * For mca_asm.S we want to access the stack physically since the state is saved before we
- * go virtual and don't want to destroy the iip or ipsr.
- */
-#define MINSTATE_START_SAVE_MIN_PHYS                                                           \
-(pKStk) mov r3=IA64_KR(PER_CPU_DATA);;                                                         \
-(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;;                                                   \
-(pKStk) ld8 r3 = [r3];;                                                                                \
-(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;;                                            \
-(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3;                                          \
-(pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
-(pUStk)        addl r22=IA64_RBS_OFFSET,r1;            /* compute base of register backing store */    \
-       ;;                                                                                      \
-(pUStk)        mov r24=ar.rnat;                                                                        \
-(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;   /* compute base of memory stack */      \
-(pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
-(pUStk)        dep r22=-1,r22,61,3;                    /* compute kernel virtual addr of RBS */        \
-       ;;                                                                                      \
-(pUStk)        mov ar.bspstore=r22;                    /* switch to kernel RBS */                      \
-       ;;                                                                                      \
-(pUStk)        mov r18=ar.bsp;                                                                         \
-(pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */             \
-
-#define MINSTATE_END_SAVE_MIN_PHYS                                                             \
-       dep r12=-1,r12,61,3;            /* make sp a kernel virtual address */                  \
-       ;;
-
-#ifdef MINSTATE_VIRT
-# define MINSTATE_GET_CURRENT(reg)     mov reg=IA64_KR(CURRENT)
-# define MINSTATE_START_SAVE_MIN       MINSTATE_START_SAVE_MIN_VIRT
-# define MINSTATE_END_SAVE_MIN         MINSTATE_END_SAVE_MIN_VIRT
-#endif
-
-#ifdef MINSTATE_PHYS
-# define MINSTATE_GET_CURRENT(reg)     mov reg=IA64_KR(CURRENT);; tpa reg=reg
-# define MINSTATE_START_SAVE_MIN       MINSTATE_START_SAVE_MIN_PHYS
-# define MINSTATE_END_SAVE_MIN         MINSTATE_END_SAVE_MIN_PHYS
-#endif
-
 /*
  * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
  * the minimum state necessary that allows us to turn psr.ic back
@@ -97,7 +30,7 @@
  * we can pass interruption state as arguments to a handler.
  */
 #define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)                                                      \
-       MINSTATE_GET_CURRENT(r16);      /* M (or M;;I) */                                       \
+       mov r16=IA64_KR(CURRENT);       /* M */                                                 \
        mov r27=ar.rsc;                 /* M */                                                 \
        mov r20=r1;                     /* A */                                                 \
        mov r25=ar.unat;                /* M */                                                 \
        SAVE_IFS;                                                                               \
        cmp.eq pKStk,pUStk=r0,r17;              /* are we in kernel mode already? */            \
        ;;                                                                                      \
-       MINSTATE_START_SAVE_MIN                                                                 \
+(pUStk)        mov ar.rsc=0;           /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */     \
+       ;;                                                                                      \
+(pUStk)        mov.m r24=ar.rnat;                                                                      \
+(pUStk)        addl r22=IA64_RBS_OFFSET,r1;                    /* compute base of RBS */               \
+(pKStk) mov r1=sp;                                     /* get sp  */                           \
+       ;;                                                                                      \
+(pUStk) lfetch.fault.excl.nt1 [r22];                                                           \
+(pUStk)        addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;   /* compute base of memory stack */      \
+(pUStk)        mov r23=ar.bspstore;                            /* save ar.bspstore */                  \
+       ;;                                                                                      \
+(pUStk)        mov ar.bspstore=r22;                            /* switch to kernel RBS */              \
+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1;                 /* if in kernel mode, use sp (r12) */   \
+       ;;                                                                                      \
+(pUStk)        mov r18=ar.bsp;                                                                         \
+(pUStk)        mov ar.rsc=0x3;         /* set eager mode, pl 0, little-endian, loadrs=0 */             \
        adds r17=2*L1_CACHE_BYTES,r1;           /* really: biggest cache-line size */           \
        adds r16=PT(CR_IPSR),r1;                                                                \
        ;;                                                                                      \
        EXTRA;                                                                                  \
        movl r1=__gp;           /* establish kernel global pointer */                           \
        ;;                                                                                      \
-       MINSTATE_END_SAVE_MIN
+       bsw.1;                  /* switch back to bank 1 (must be last in insn group) */        \
+       ;;
 
 /*
  * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
index 25e7c834456402502edf40986c9572649a63c92b..89faa603c6be239f3630a88dcbfb8f7338d5838f 100644 (file)
@@ -307,11 +307,9 @@ vm_info(char *page)
 
        if ((status = ia64_pal_vm_summary(&vm_info_1, &vm_info_2)) !=0) {
                printk(KERN_ERR "ia64_pal_vm_summary=%ld\n", status);
-               return 0;
-       }
+       } else {
 
-
-       p += sprintf(p,
+               p += sprintf(p,
                     "Physical Address Space         : %d bits\n"
                     "Virtual Address Space          : %d bits\n"
                     "Protection Key Registers(PKR)  : %d\n"
@@ -319,92 +317,99 @@ vm_info(char *page)
                     "Hash Tag ID                    : 0x%x\n"
                     "Size of RR.rid                 : %d\n",
                     vm_info_1.pal_vm_info_1_s.phys_add_size,
-                    vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,
-                    vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,
+                    vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
+                    vm_info_1.pal_vm_info_1_s.max_pkr+1,
+                    vm_info_1.pal_vm_info_1_s.key_size,
+                    vm_info_1.pal_vm_info_1_s.hash_tag_id,
                     vm_info_2.pal_vm_info_2_s.rid_size);
+       }
 
-       if (ia64_pal_mem_attrib(&attrib) != 0)
-               return 0;
-
-       p += sprintf(p, "Supported memory attributes    : ");
-       sep = "";
-       for (i = 0; i < 8; i++) {
-               if (attrib & (1 << i)) {
-                       p += sprintf(p, "%s%s", sep, mem_attrib[i]);
-                       sep = ", ";
+       if (ia64_pal_mem_attrib(&attrib) == 0) {
+               p += sprintf(p, "Supported memory attributes    : ");
+               sep = "";
+               for (i = 0; i < 8; i++) {
+                       if (attrib & (1 << i)) {
+                               p += sprintf(p, "%s%s", sep, mem_attrib[i]);
+                               sep = ", ";
+                       }
                }
+               p += sprintf(p, "\n");
        }
-       p += sprintf(p, "\n");
 
        if ((status = ia64_pal_vm_page_size(&tr_pages, &vw_pages)) !=0) {
                printk(KERN_ERR "ia64_pal_vm_page_size=%ld\n", status);
-               return 0;
-       }
-
-       p += sprintf(p,
-                    "\nTLB walker                     : %simplemented\n"
-                    "Number of DTR                  : %d\n"
-                    "Number of ITR                  : %d\n"
-                    "TLB insertable page sizes      : ",
-                    vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
-                    vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
-                    vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
+       } else {
 
+               p += sprintf(p,
+                            "\nTLB walker                     : %simplemented\n"
+                            "Number of DTR                  : %d\n"
+                            "Number of ITR                  : %d\n"
+                            "TLB insertable page sizes      : ",
+                            vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
+                            vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
+                            vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
 
-       p = bitvector_process(p, tr_pages);
 
-       p += sprintf(p, "\nTLB purgeable page sizes       : ");
+               p = bitvector_process(p, tr_pages);
 
-       p = bitvector_process(p, vw_pages);
+               p += sprintf(p, "\nTLB purgeable page sizes       : ");
 
+               p = bitvector_process(p, vw_pages);
+       }
        if ((status=ia64_get_ptce(&ptce)) != 0) {
                printk(KERN_ERR "ia64_get_ptce=%ld\n", status);
-               return 0;
-       }
-
-       p += sprintf(p,
+       } else {
+               p += sprintf(p,
                     "\nPurge base address             : 0x%016lx\n"
                     "Purge outer loop count         : %d\n"
                     "Purge inner loop count         : %d\n"
                     "Purge outer loop stride        : %d\n"
                     "Purge inner loop stride        : %d\n",
-                    ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);
+                    ptce.base, ptce.count[0], ptce.count[1],
+                    ptce.stride[0], ptce.stride[1]);
 
-       p += sprintf(p,
+               p += sprintf(p,
                     "TC Levels                      : %d\n"
                     "Unique TC(s)                   : %d\n",
                     vm_info_1.pal_vm_info_1_s.num_tc_levels,
                     vm_info_1.pal_vm_info_1_s.max_unique_tcs);
 
-       for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
-               for (j=2; j>0 ; j--) {
-                       tc_pages = 0; /* just in case */
+               for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
+                       for (j=2; j>0 ; j--) {
+                               tc_pages = 0; /* just in case */
 
 
-                       /* even without unification, some levels may not be present */
-                       if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
-                               continue;
-                       }
+                               /* even without unification, some levels may not be present */
+                               if ((status=ia64_pal_vm_info(i,j, &tc_info, &tc_pages)) != 0) {
+                                       continue;
+                               }
 
-                       p += sprintf(p,
+                               p += sprintf(p,
                                     "\n%s Translation Cache Level %d:\n"
                                     "\tHash sets           : %d\n"
                                     "\tAssociativity       : %d\n"
                                     "\tNumber of entries   : %d\n"
                                     "\tFlags               : ",
-                                    cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,
-                                    tc_info.tc_associativity, tc_info.tc_num_entries);
+                                    cache_types[j+tc_info.tc_unified], i+1,
+                                    tc_info.tc_num_sets,
+                                    tc_info.tc_associativity,
+                                    tc_info.tc_num_entries);
 
-                       if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");
-                       if (tc_info.tc_unified) p += sprintf(p, "Unified ");
-                       if (tc_info.tc_reduce_tr) p += sprintf(p, "TCReduction");
+                               if (tc_info.tc_pf)
+                                       p += sprintf(p, "PreferredPageSizeOptimized ");
+                               if (tc_info.tc_unified)
+                                       p += sprintf(p, "Unified ");
+                               if (tc_info.tc_reduce_tr)
+                                       p += sprintf(p, "TCReduction");
 
-                       p += sprintf(p, "\n\tSupported page sizes: ");
+                               p += sprintf(p, "\n\tSupported page sizes: ");
 
-                       p = bitvector_process(p, tc_pages);
+                               p = bitvector_process(p, tc_pages);
 
-                       /* when unified date (j=2) is enough */
-                       if (tc_info.tc_unified) break;
+                               /* when unified date (j=2) is enough */
+                               if (tc_info.tc_unified)
+                                       break;
+                       }
                }
        }
        p += sprintf(p, "\n");
@@ -440,14 +445,14 @@ register_info(char *page)
                p += sprintf(p, "\n");
        }
 
-       if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;
+       if (ia64_pal_rse_info(&phys_stacked, &hints) == 0) {
 
        p += sprintf(p,
                     "RSE stacked physical registers   : %ld\n"
                     "RSE load/store hints             : %ld (%s)\n",
                     phys_stacked, hints.ph_data,
                     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
-
+       }
        if (ia64_pal_debug_info(&iregs, &dregs))
                return 0;
 
index f1201ac8a11617b012ec9e8a25c1b6cf20863d80..1650353e3f77ef40cdf5ab96e4642e67eb8b4190 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/pagemap.h>
 #include <linux/mount.h>
 #include <linux/bitops.h>
+#include <linux/rcupdate.h>
 
 #include <asm/errno.h>
 #include <asm/intrinsics.h>
@@ -496,7 +497,7 @@ typedef struct {
 static pfm_stats_t             pfm_stats[NR_CPUS];
 static pfm_session_t           pfm_sessions;   /* global sessions information */
 
-static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pfm_alt_install_check);
 static pfm_intr_handler_desc_t  *pfm_alt_intr_handler;
 
 static struct proc_dir_entry   *perfmon_dir;
@@ -2217,15 +2218,17 @@ static void
 pfm_free_fd(int fd, struct file *file)
 {
        struct files_struct *files = current->files;
+       struct fdtable *fdt = files_fdtable(files);
 
        /* 
         * there ie no fd_uninstall(), so we do it here
         */
        spin_lock(&files->file_lock);
-        files->fd[fd] = NULL;
+       rcu_assign_pointer(fdt->fd[fd], NULL);
        spin_unlock(&files->file_lock);
 
-       if (file) put_filp(file);
+       if (file)
+               put_filp(file);
        put_unused_fd(fd);
 }
 
index 6f0cc7a6634ee84a00147630e0815c072a3edc4a..ca68e6e44a7272275602b8914cd87166a70f5d3e 100644 (file)
  *
  * Dec  5 2004 kaos@sgi.com
  *   Standardize which records are cleared automatically.
+ *
+ * Aug 18 2005 kaos@sgi.com
+ *   mca.c may not pass a buffer, a NULL buffer just indicates that a new
+ *   record is available in SAL.
+ *   Replace some NR_CPUS by cpus_online, for hotplug cpu.
  */
 
 #include <linux/types.h>
@@ -193,7 +198,7 @@ shift1_data_saved (struct salinfo_data *data, int shift)
  * The buffer passed from mca.c points to the output from ia64_log_get. This is
  * a persistent buffer but its contents can change between the interrupt and
  * when user space processes the record.  Save the record id to identify
- * changes.
+ * changes.  If the buffer is NULL then just update the bitmap.
  */
 void
 salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
@@ -206,27 +211,29 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
 
        BUG_ON(type >= ARRAY_SIZE(salinfo_log_name));
 
-       if (irqsafe)
-               spin_lock_irqsave(&data_saved_lock, flags);
-       for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
-               if (!data_saved->buffer)
-                       break;
-       }
-       if (i == saved_size) {
-               if (!data->saved_num) {
-                       shift1_data_saved(data, 0);
-                       data_saved = data->data_saved + saved_size - 1;
-               } else
-                       data_saved = NULL;
-       }
-       if (data_saved) {
-               data_saved->cpu = smp_processor_id();
-               data_saved->id = ((sal_log_record_header_t *)buffer)->id;
-               data_saved->size = size;
-               data_saved->buffer = buffer;
+       if (buffer) {
+               if (irqsafe)
+                       spin_lock_irqsave(&data_saved_lock, flags);
+               for (i = 0, data_saved = data->data_saved; i < saved_size; ++i, ++data_saved) {
+                       if (!data_saved->buffer)
+                               break;
+               }
+               if (i == saved_size) {
+                       if (!data->saved_num) {
+                               shift1_data_saved(data, 0);
+                               data_saved = data->data_saved + saved_size - 1;
+                       } else
+                               data_saved = NULL;
+               }
+               if (data_saved) {
+                       data_saved->cpu = smp_processor_id();
+                       data_saved->id = ((sal_log_record_header_t *)buffer)->id;
+                       data_saved->size = size;
+                       data_saved->buffer = buffer;
+               }
+               if (irqsafe)
+                       spin_unlock_irqrestore(&data_saved_lock, flags);
        }
-       if (irqsafe)
-               spin_unlock_irqrestore(&data_saved_lock, flags);
 
        if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
                if (irqsafe)
@@ -244,7 +251,7 @@ salinfo_timeout_check(struct salinfo_data *data)
        int i;
        if (!data->open)
                return;
-       for (i = 0; i < NR_CPUS; ++i) {
+       for_each_online_cpu(i) {
                if (test_bit(i, &data->cpu_event)) {
                        /* double up() is not a problem, user space will see no
                         * records for the additional "events".
@@ -291,7 +298,7 @@ retry:
 
        n = data->cpu_check;
        for (i = 0; i < NR_CPUS; i++) {
-               if (test_bit(n, &data->cpu_event)) {
+               if (test_bit(n, &data->cpu_event) && cpu_online(n)) {
                        cpu = n;
                        break;
                }
@@ -585,11 +592,10 @@ salinfo_init(void)
 
                /* we missed any events before now */
                online = 0;
-               for (j = 0; j < NR_CPUS; j++)
-                       if (cpu_online(j)) {
-                               set_bit(j, &data->cpu_event);
-                               ++online;
-                       }
+               for_each_online_cpu(j) {
+                       set_bit(j, &data->cpu_event);
+                       ++online;
+               }
                sema_init(&data->sem, online);
 
                *sdir++ = dir;
index 3288be47bc75850e46b1500fb91321d0a4b51055..93d5a3b41f69e9e0bb2efb32c982e6113edbc809 100644 (file)
@@ -2019,28 +2019,6 @@ init_frame_info (struct unw_frame_info *info, struct task_struct *t,
        STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
 }
 
-void
-unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t,
-                           struct pt_regs *pt, struct switch_stack *sw)
-{
-       unsigned long sof;
-
-       init_frame_info(info, t, sw, pt->r12);
-       info->cfm_loc = &pt->cr_ifs;
-       info->unat_loc = &pt->ar_unat;
-       info->pfs_loc = &pt->ar_pfs;
-       sof = *info->cfm_loc & 0x7f;
-       info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof);
-       info->ip = pt->cr_iip + ia64_psr(pt)->ri;
-       info->pt = (unsigned long) pt;
-       UNW_DPRINT(3, "unwind.%s:\n"
-                  "  bsp    0x%lx\n"
-                  "  sof    0x%lx\n"
-                  "  ip     0x%lx\n",
-                  __FUNCTION__, info->bsp, sof, info->ip);
-       find_save_locs(info);
-}
-
 void
 unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
 {
index 65f9958db9f03347a2a49c3b69a564c536459529..1281c609ee98b27ccc94e246424b7de653910ff0 100644 (file)
@@ -382,13 +382,22 @@ ia64_mmu_init (void *my_cpu_data)
 
        if (impl_va_bits < 51 || impl_va_bits > 61)
                panic("CPU has bogus IMPL_VA_MSB value of %lu!\n", impl_va_bits - 1);
+       /*
+        * mapped_space_bits - PAGE_SHIFT is the total number of ptes we need,
+        * which must fit into "vmlpt_bits - pte_bits" slots. Second half of
+        * the test makes sure that our mapped space doesn't overlap the
+        * unimplemented hole in the middle of the region.
+        */
+       if ((mapped_space_bits - PAGE_SHIFT > vmlpt_bits - pte_bits) ||
+           (mapped_space_bits > impl_va_bits - 1))
+               panic("Cannot build a big enough virtual-linear page table"
+                     " to cover mapped address space.\n"
+                     " Try using a smaller page size.\n");
+
 
        /* place the VMLPT at the end of each page-table mapped region: */
        pta = POW2(61) - POW2(vmlpt_bits);
 
-       if (POW2(mapped_space_bits) >= pta)
-               panic("mm/init: overlap between virtually mapped linear page table and "
-                     "mapped kernel space!");
        /*
         * Set the (virtually mapped linear) page table address.  Bit
         * 8 selects between the short and long format, bits 2-7 the
index 14908ad7db8c1f3d863ae2f06d20c2fbe43331e4..6f8c5883716b0bd7858b14798102b77073a2c4a8 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/sn/clksupport.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/geo.h>
+#include <asm/sn/sn_feature_sets.h>
 #include "xtalk/xwidgetdev.h"
 #include "xtalk/hubdev.h"
 #include <asm/sn/klconfig.h>
@@ -97,6 +98,7 @@ EXPORT_SYMBOL(sn_region_size);
 int sn_prom_type;      /* 0=hardware, 1=medusa/realprom, 2=medusa/fakeprom */
 
 short physical_node_map[MAX_PHYSNODE_ID];
+static unsigned long sn_prom_features[MAX_PROM_FEATURE_SETS];
 
 EXPORT_SYMBOL(physical_node_map);
 
@@ -271,7 +273,10 @@ void __init sn_setup(char **cmdline_p)
        u32 version = sn_sal_rev();
        extern void sn_cpu_init(void);
 
-       ia64_sn_plat_set_error_handling_features();
+       ia64_sn_plat_set_error_handling_features();     // obsolete
+       ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
+       ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
+
 
 #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
        /*
@@ -314,16 +319,6 @@ void __init sn_setup(char **cmdline_p)
 
        printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
 
-       /*
-        * Confirm the SAL we're running on is recent enough...
-        */
-       if (version < SN_SAL_MIN_VERSION) {
-               printk(KERN_ERR "This kernel needs SGI SAL version >= "
-                      "%x.%02x\n", SN_SAL_MIN_VERSION >> 8,
-                       SN_SAL_MIN_VERSION & 0x00FF);
-               panic("PROM version too old\n");
-       }
-
        master_nasid = boot_get_nasid();
 
        status =
@@ -480,6 +475,10 @@ void __init sn_cpu_init(void)
        if (nodepdaindr[0] == NULL)
                return;
 
+       for (i = 0; i < MAX_PROM_FEATURE_SETS; i++)
+               if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)
+                       break;
+
        cpuid = smp_processor_id();
        cpuphyid = get_sapicid();
 
@@ -651,3 +650,12 @@ nasid_slice_to_cpuid(int nasid, int slice)
 
        return -1;
 }
+
+int sn_prom_feature_available(int id)
+{
+       if (id >= BITS_PER_LONG * MAX_PROM_FEATURE_SETS)
+               return 0;
+       return test_bit(id, sn_prom_features);
+}
+EXPORT_SYMBOL(sn_prom_feature_available);
+
index d0c2c114a459a5c694402e540eb7468afb137dec..e5c6d3c0a8e9a852ac37ae43e620ffa820bc0b05 100644 (file)
@@ -130,7 +130,7 @@ struct net_device *xpnet_device;
  */
 static u64 xpnet_broadcast_partitions;
 /* protect above */
-static spinlock_t xpnet_broadcast_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(xpnet_broadcast_lock);
 
 /*
  * Since the Block Transfer Engine (BTE) is being used for the transfer
index 7622d4ec5f08d2ff995b9a05e10fdefb63630fbe..1ef3987ebc6ac28e31cd1242e9c6e07b34b8ebb2 100644 (file)
@@ -242,8 +242,8 @@ config SMP
          Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
          Management" code will be disabled if you say Y here.
 
-         See also the <file:Documentation/smp.tex>,
-         <file:Documentation/smp.txt> and the SMP-HOWTO available at
+         See also the <file:Documentation/smp.txt>,
+         and the SMP-HOWTO available at
          <http://www.linuxdoc.org/docs.html#howto>.
 
          If you don't know what to do here, say N.
diff --git a/arch/m32r/kernel/asm-offsets.c b/arch/m32r/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..9e26311
--- /dev/null
@@ -0,0 +1 @@
+/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
index 48b187f2d2b350d5cd5da50ba71e1a9b8664a8c6..a4576ac7e8702c27e787f8f0c7d87d0c61285f26 100644 (file)
@@ -892,7 +892,6 @@ unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
        int try)
 {
        spinlock_t *ipilock;
-       unsigned long flags = 0;
        volatile unsigned long *ipicr_addr;
        unsigned long ipicr_val;
        unsigned long my_physid_mask;
@@ -916,50 +915,27 @@ unsigned long send_IPI_mask_phys(cpumask_t physid_mask, int ipi_num,
         * write IPICRi (send IPIi)
         * unlock ipi_lock[i]
         */
+       spin_lock(ipilock);
        __asm__ __volatile__ (
-               ";; LOCK ipi_lock[i]            \n\t"
+               ";; CHECK IPICRi == 0           \n\t"
                ".fillinsn                      \n"
                "1:                             \n\t"
-               "mvfc   %1, psw                 \n\t"
-               "clrpsw #0x40 -> nop            \n\t"
-               DCACHE_CLEAR("r4", "r5", "%2")
-               "lock   r4, @%2                 \n\t"
-               "addi   r4, #-1                 \n\t"
-               "unlock r4, @%2                 \n\t"
-               "mvtc   %1, psw                 \n\t"
-               "bnez   r4, 2f                  \n\t"
-               LOCK_SECTION_START(".balign 4 \n\t")
-               ".fillinsn                      \n"
-               "2:                             \n\t"
-               "ld     r4, @%2                 \n\t"
-               "blez   r4, 2b                  \n\t"
+               "ld     %0, @%1                 \n\t"
+               "and    %0, %4                  \n\t"
+               "beqz   %0, 2f                  \n\t"
+               "bnez   %3, 3f                  \n\t"
                "bra    1b                      \n\t"
-               LOCK_SECTION_END
-               ";; CHECK IPICRi == 0           \n\t"
-               ".fillinsn                      \n"
-               "3:                             \n\t"
-               "ld     %0, @%3                 \n\t"
-               "and    %0, %6                  \n\t"
-               "beqz   %0, 4f                  \n\t"
-               "bnez   %5, 5f                  \n\t"
-               "bra    3b                      \n\t"
                ";; WRITE IPICRi (send IPIi)    \n\t"
                ".fillinsn                      \n"
-               "4:                             \n\t"
-               "st     %4, @%3                 \n\t"
-               ";; UNLOCK ipi_lock[i]          \n\t"
+               "2:                             \n\t"
+               "st     %2, @%1                 \n\t"
                ".fillinsn                      \n"
-               "5:                             \n\t"
-               "ldi    r4, #1                  \n\t"
-               "st     r4, @%2                 \n\t"
+               "3:                             \n\t"
                : "=&r"(ipicr_val)
-               : "r"(flags), "r"(&ipilock->slock), "r"(ipicr_addr),
-                 "r"(mask), "r"(try), "r"(my_physid_mask)
-               : "memory", "r4"
-#ifdef CONFIG_CHIP_M32700_TS1
-               , "r5"
-#endif /* CONFIG_CHIP_M32700_TS1 */
+               : "r"(ipicr_addr), "r"(mask), "r"(try), "r"(my_physid_mask)
+               : "memory"
        );
+       spin_unlock(ipilock);
 
        return ipicr_val;
 }
index 466e7407afc7b40b34dd149240ebf56b904a8913..34d826d10f1b6f1683b04d0daa254c6f8ce1b969 100644 (file)
@@ -113,14 +113,5 @@ else
        bzip2 -1c vmlinux >vmlinux.bz2
 endif
 
-prepare: include/asm-$(ARCH)/offsets.h
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
 archclean:
        rm -f vmlinux.gz vmlinux.bz2
index cb5d93630467230ac6f9de5d2e9a0f468a859f8d..bd5d134e9f123856fc052ad5139a7a137b848d6a 100644 (file)
@@ -63,7 +63,7 @@ void __init amiga_init_sound(void)
 }
 
 static void nosound( unsigned long ignored );
-static struct timer_list sound_timer = TIMER_INITIALIZER(nosound, 0, 0);
+static DEFINE_TIMER(sound_timer, nosound, 0, 0);
 
 void amiga_mksound( unsigned int hz, unsigned int ticks )
 {
index dbc1255a5e994f2465d1f18d0615e016c49d6e11..9571a21d6ad42b0d0f9de6a63038fd1d4f5cee9c 100644 (file)
@@ -40,7 +40,7 @@
 
 #include <linux/linkage.h>
 #include <asm/entry.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 |SKELETON      idnt    2,1 | Motorola 040 Floating Point Software Package
 
index 803a6ecdda81c330aa8428ebc5e87e80eedc6083..4ba2c74da93da6070d80e26cd754ca59b671d046 100644 (file)
@@ -36,7 +36,7 @@
 
 #include <linux/linkage.h>
 #include <asm/entry.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 
 |################################
index e964015a31dc96a905f98e91f5665a3bc243db9c..23ca60a4555249af81024a3d53b27ba2e8a28d03 100644 (file)
@@ -42,7 +42,7 @@
 #include <asm/traps.h>
 #include <asm/unistd.h>
 
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 .globl system_call, buserr, trap
 .globl resume, ret_from_exception
index 7cd6de17c20d49909b8bc1d0d3c0d00f1262d1db..d4336d846df146c8e3f6f771481c1e19c360a144 100644 (file)
 #include <asm/entry.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #ifdef CONFIG_MAC
 
index 44c5cd2ad6a8d6c2ec9969df090625205ff67b39..8f0640847ad2bf7bf99d0a184ed10ce8272a84f8 100644 (file)
@@ -56,8 +56,7 @@ static void ( *mac_special_bell )( unsigned int, unsigned int, unsigned int );
 /*
  * our timer to start/continue/stop the bell
  */
-static struct timer_list mac_sound_timer =
-               TIMER_INITIALIZER(mac_nosound, 0, 0);
+static DEFINE_TIMER(mac_sound_timer, mac_nosound, 0, 0);
 
 /*
  * Sort of initialize the sound chip (called from mac_mksound on the first
index 1d6edc975d89c10cfe817820d9ef9f40d5bebf52..c1ecfef7886a6618e0a500c5cf366e46cd6762a4 100644 (file)
@@ -39,7 +39,7 @@
 #define _FP_EMU_H
 
 #ifdef __ASSEMBLY__
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #endif
 #include <asm/math-emu.h>
 
index 7ce5e55b2401e40716faeaaf5fdacbe903cfea2f..b8fdf191b8f6b3e95d05830f13dc33e7b06c1425 100644 (file)
@@ -102,21 +102,11 @@ CFLAGS += -DUTS_SYSNAME=\"uClinux\"
 
 head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o
 
-CLEAN_FILES := include/asm-$(ARCH)/asm-offsets.h \
-              arch/$(ARCH)/kernel/asm-offsets.s
-
 core-y += arch/m68knommu/kernel/ \
           arch/m68knommu/mm/ \
           $(CLASSDIR) \
           arch/m68knommu/platform/$(PLATFORM)/
 libs-y += arch/m68knommu/lib/
 
-prepare: include/asm-$(ARCH)/asm-offsets.h
-
 archclean:
        $(Q)$(MAKE) $(clean)=arch/m68knommu/boot
-
-include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
-                                  include/asm include/linux/version.h \
-                                  include/config/MARKER
-       $(call filechk,gen-asm-offsets)
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
new file mode 100644 (file)
index 0000000..a5c639a
--- /dev/null
@@ -0,0 +1,408 @@
+/* arch/m68knommu/platform/68360/head-ram.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#define ASSEMBLY
+#include <linux/config.h>
+
+.global _stext
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000002
+#define SIM_BR0_MASK                0x00000001
+
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+       
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+       .text
+_start:
+_stext:
+       nop
+       ori.w   #MCU_DISABLE_INTRPTS, %sr       /* disable interrupts: */
+       /* We should not need to setup the boot stack the reset should do it. */
+       movea.l #__ramend, %sp                  /*set up stack at the end of DRAM:*/
+
+set_mbar_register:
+       moveq.l #0x07, %d1                      /* Setup MBAR */
+       movec   %d1, %dfc
+
+       lea.l   MCU_SIM_MBAR_ADRS, %a0
+       move.l  #_dprbase, %d0
+       andi.l  #MCU_SIM_MBAR_BA_MASK, %d0
+       ori.l   #MCU_SIM_MBAR_AS_MASK, %d0
+       moves.l %d0, %a0@
+
+       moveq.l #0x05, %d1
+       movec.l %d1, %dfc
+
+       /* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+       /* Set Module Configuration Register */
+       move.l  #MCU_SIM_MCR, MCR
+
+       /* to do:       Determine cause of reset */
+
+       /*
+        *       configure system clock MC68360 p. 6-40
+        *       (value +1)*osc/128 = system clock
+        */
+set_sim_clock:
+       move.w  #MCU_SIM_PLLCR, PLLCR
+       move.b  #MCU_SIM_CLKOCR, CLKOCR
+       move.w  #MCU_SIM_CDVCR, CDVCR
+
+       /* Wait for the PLL to settle */
+       move.w  #16384, %d0
+pll_settle_wait:
+       subi.w  #1, %d0
+       bne     pll_settle_wait
+
+       /* Setup the system protection register, and watchdog timer register */
+       move.b  #MCU_SIM_SWIV, SWIV
+       move.w  #MCU_SIM_PICR, PICR
+       move.w  #MCU_SIM_PITR, PITR
+       move.w  #MCU_SIM_SYPCR, SYPCR
+
+       /* Clear DPRAM - system + parameter */
+       movea.l #_dprbase, %a0
+       movea.l #_dprbase+0x2000, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     clear_dpram
+
+configure_memory_controller:    
+       /* Set up Global Memory Register (GMR) */
+       move.l  #MCU_SIM_GMR, %d0
+       move.l  %d0, GMR
+
+configure_chip_select_0:
+       move.l  #__ramend, %d0
+       subi.l  #__ramstart, %d0
+       subq.l  #0x01, %d0
+       eori.l  #SIM_OR_MASK, %d0
+       ori.l   #SIM_OR0_MASK, %d0
+       move.l  %d0, OR0
+
+       move.l  #__ramstart, %d0
+       ori.l   #SIM_BR0_MASK, %d0
+       move.l  %d0, BR0
+
+configure_chip_select_1:
+       move.l  #__rom_end, %d0
+       subi.l  #__rom_start, %d0
+       subq.l  #0x01, %d0
+       eori.l  #SIM_OR_MASK, %d0
+       ori.l   #SIM_OR1_MASK, %d0
+       move.l  %d0, OR1
+
+       move.l  #__rom_start, %d0
+       ori.l   #SIM_BR1_MASK, %d0
+       move.l  %d0, BR1
+
+       move.w  #MCU_SIM_PEPAR, PEPAR 
+
+       /* point to vector table: */
+       move.l  #_romvec, %a0
+       move.l  #_ramvec, %a1
+copy_vectors:
+       move.l  %a0@, %d0
+       move.l  %d0, %a1@
+       move.l  %a0@, %a1@
+       addq.l  #0x04, %a0
+       addq.l  #0x04, %a1
+       cmp.l   #_start, %a0
+       blt     copy_vectors
+
+       move.l  #_ramvec, %a1
+       movec   %a1, %vbr
+
+
+       /* Copy data segment from ROM to RAM */
+       moveal  #_stext, %a0
+       moveal  #_sdata, %a1
+       moveal  #_edata, %a2
+
+       /* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+       move.l  %a0@, %d0
+       addq.l  #0x04, %a0
+       move.l  %d0, %a1@
+       addq.l  #0x04, %a1
+       cmp.l   #_edata, %a1
+       blt     LD1
+
+       moveal  #_sbss, %a0
+       moveal  #_ebss, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     L1
+
+load_quicc:
+       move.l  #_dprbase, _quicc_base
+
+store_ram_size:
+       /* Set ram size information */
+       move.l  #_sdata, _rambase
+       move.l  #_ebss, _ramstart
+       move.l  #__ramend, %d0
+       sub.l   #0x1000, %d0                    /* Reserve 4K for stack space.*/
+       move.l  %d0, _ramend                    /* Different from __ramend.*/
+
+store_flash_size:
+       /* Set rom size information */
+       move.l  #__rom_end, %d0
+       sub.l   #__rom_start, %d0
+       move.l  %d0, rom_length
+    
+       pea     0
+       pea     env
+       pea     %sp@(4)
+       pea     0
+
+       lea     init_thread_union, %a2
+       lea     0x2000(%a2), %sp
+
+lp:
+       jsr     start_kernel
+
+_exit:
+       jmp     _exit
+
+
+       .data
+       .align 4
+env:
+       .long   0
+_quicc_base:
+       .long   0
+_periph_base:
+       .long   0
+_ramvec:
+       .long   0
+_rambase:
+       .long   0
+_ramstart:
+       .long   0
+_ramend:
+       .long   0
+_dprbase:
+       .long   0xffffe000
+
+       .text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+.section ".data.initvect","awx"
+    .long   __ramend   /* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68knommu/platform/68360/head-rom.S
new file mode 100644 (file)
index 0000000..0da357a
--- /dev/null
@@ -0,0 +1,420 @@
+/* arch/m68knommu/platform/68360/head-rom.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#include <linux/config.h>
+
+.global _stext
+.global _sbss
+.global _start
+
+.global _rambase
+.global __ramvec
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+
+#define OR2                         (_dprbase + REGB + 0x0074)
+#define BR2                         (_dprbase + REGB + 0x0070)
+
+#define OR3                         (_dprbase + REGB + 0x0084)
+#define BR3                         (_dprbase + REGB + 0x0080)
+
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+
+#define OR5                         (_dprbase + REGB + 0x00A4)
+#define BR5                         (_dprbase + REGB + 0x00A0)
+
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000000
+#define SIM_BR0_MASK                0x00000001
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+       
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+       .text
+_start:
+_stext:
+       nop
+       ori.w   #MCU_DISABLE_INTRPTS, %sr       /* disable interrupts: */
+       /* We should not need to setup the boot stack the reset should do it. */
+       movea.l #__ramend, %sp          /* set up stack at the end of DRAM:*/
+
+
+set_mbar_register:
+       moveq.l #0x07, %d1                      /* Setup MBAR */
+       movec   %d1, %dfc
+
+       lea.l   MCU_SIM_MBAR_ADRS, %a0
+       move.l  #_dprbase, %d0
+       andi.l  #MCU_SIM_MBAR_BA_MASK, %d0
+       ori.l   #MCU_SIM_MBAR_AS_MASK, %d0
+       moves.l %d0, %a0@
+
+       moveq.l #0x05, %d1
+       movec.l %d1, %dfc
+
+       /* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+       /* Set Module Configuration Register */
+       move.l  #MCU_SIM_MCR, MCR
+
+       /* to do:       Determine cause of reset */
+
+       /*
+        *      configure system clock MC68360 p. 6-40
+        *      (value +1)*osc/128 = system clock
+        *                    or
+        *      (value + 1)*osc = system clock
+        *      You do not need to divide the oscillator by 128 unless you want to.
+        */
+set_sim_clock:
+       move.w  #MCU_SIM_PLLCR, PLLCR
+       move.b  #MCU_SIM_CLKOCR, CLKOCR
+       move.w  #MCU_SIM_CDVCR, CDVCR
+
+       /* Wait for the PLL to settle */
+       move.w  #16384, %d0
+pll_settle_wait:
+       subi.w  #1, %d0
+       bne     pll_settle_wait
+
+       /* Setup the system protection register, and watchdog timer register */
+       move.b  #MCU_SIM_SWIV, SWIV
+       move.w  #MCU_SIM_PICR, PICR
+       move.w  #MCU_SIM_PITR, PITR
+       move.w  #MCU_SIM_SYPCR, SYPCR
+
+       /* Clear DPRAM - system + parameter */
+       movea.l #_dprbase, %a0
+       movea.l #_dprbase+0x2000, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     clear_dpram
+
+configure_memory_controller:    
+       /* Set up Global Memory Register (GMR) */
+       move.l  #MCU_SIM_GMR, %d0
+       move.l  %d0, GMR
+
+configure_chip_select_0:
+       move.l  #0x00400000, %d0
+       subq.l  #0x01, %d0
+       eori.l  #SIM_OR_MASK, %d0
+       ori.l   #SIM_OR0_MASK, %d0
+       move.l  %d0, OR0
+
+       move.l  #__rom_start, %d0
+       ori.l   #SIM_BR0_MASK, %d0
+       move.l  %d0, BR0
+
+       move.l  #0x0, BR1
+       move.l  #0x0, BR2
+       move.l  #0x0, BR3
+       move.l  #0x0, BR4
+       move.l  #0x0, BR5
+       move.l  #0x0, BR6
+       move.l  #0x0, BR7
+
+       move.w  #MCU_SIM_PEPAR, PEPAR 
+
+       /* point to vector table: */
+       move.l  #_romvec, %a0
+       move.l  #_ramvec, %a1
+copy_vectors:
+       move.l  %a0@, %d0
+       move.l  %d0, %a1@
+       move.l  %a0@, %a1@
+       addq.l  #0x04, %a0
+       addq.l  #0x04, %a1
+       cmp.l   #_start, %a0
+       blt     copy_vectors
+
+       move.l  #_ramvec, %a1
+       movec   %a1, %vbr
+
+
+       /* Copy data segment from ROM to RAM */
+       moveal  #_etext, %a0
+       moveal  #_sdata, %a1
+       moveal  #_edata, %a2
+
+       /* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+       move.l  %a0@, %d0
+       addq.l  #0x04, %a0
+       move.l  %d0, %a1@
+       addq.l  #0x04, %a1
+       cmp.l   #_edata, %a1
+       blt     LD1
+
+       moveal  #_sbss, %a0
+       moveal  #_ebss, %a1
+
+       /* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+       movel   #0, %a0@+
+       cmpal   %a0, %a1
+       bhi     L1
+
+load_quicc:
+       move.l  #_dprbase, _quicc_base
+
+store_ram_size:
+       /* Set ram size information */
+       move.l  #_sdata, _rambase
+       move.l  #_ebss, _ramstart
+       move.l  #__ramend, %d0
+       sub.l   #0x1000, %d0                    /* Reserve 4K for stack space.*/
+       move.l  %d0, _ramend                    /* Different from __ramend.*/
+
+store_flash_size:
+       /* Set rom size information */
+       move.l  #__rom_end, %d0
+       sub.l   #__rom_start, %d0
+       move.l  %d0, rom_length
+    
+       pea     0
+       pea     env
+       pea     %sp@(4)
+       pea     0
+
+       lea     init_thread_union, %a2
+       lea     0x2000(%a2), %sp
+
+lp:
+       jsr     start_kernel
+
+_exit:
+       jmp     _exit
+
+
+       .data
+       .align 4
+env:
+       .long   0
+_quicc_base:
+       .long   0
+_periph_base:
+       .long   0
+_ramvec:
+       .long   0
+_rambase:
+       .long   0
+_ramstart:
+       .long   0
+_ramend:
+       .long   0
+_dprbase:
+       .long   0xffffe000
+
+
+       .text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+.section ".data.initvect","awx"
+    .long   __ramend   /* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
index 8d76eb1ff29169080b025ca5f0a7c153c6e4e72c..0eb71ac303af2c51bb6cf8ba1db5ed9899f647de 100644 (file)
@@ -154,6 +154,13 @@ config TANBAC_TB0226
          The TANBAC Mbase(TB0226) is a MIPS-based platform manufactured by TANBAC.
          Please refer to <http://www.tanbac.co.jp/> about Mbase.
 
+config TANBAC_TB0287
+       bool "Support for TANBAC Mini-ITX DIMM base(TB0287)"
+       depends on TANBAC_TB022X
+       help
+         The TANBAC Mini-ITX DIMM base(TB0287) is a MIPS-based platform manufactured by TANBAC.
+         Please refer to <http://www.tanbac.co.jp/> about Mini-ITX DIMM base.
+
 config VICTOR_MPC30X
        bool "Support for Victor MP-C303/304"
        depends on MACH_VR41XX
index b0fdaee8d8d95228a810f23ed680e7134022f4ee..346e803f153bc30d078c10981382c907439b5176 100644 (file)
@@ -720,38 +720,7 @@ archclean:
        @$(MAKE) $(clean)=arch/mips/boot
        @$(MAKE) $(clean)=arch/mips/lasat
 
-# Generate <asm/offset.h
-#
-# The default rule is suffering from funny problems on MIPS so we using our
-# own ...
-#
-# ---------------------------------------------------------------------------
-
-define filechk_gen-asm-offset.h
-       (set -e; \
-        echo "#ifndef _ASM_OFFSET_H"; \
-        echo "#define _ASM_OFFSET_H"; \
-        echo "/*"; \
-        echo " * DO NOT MODIFY."; \
-        echo " *"; \
-        echo " * This file was generated by arch/$(ARCH)/Makefile"; \
-        echo " *"; \
-        echo " */"; \
-        echo ""; \
-        sed -ne "/^@@@/s///p"; \
-        echo "#endif /* _ASM_OFFSET_H */" )
-endef
-
-prepare: include/asm-$(ARCH)/offset.h
-
-arch/$(ARCH)/kernel/offset.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/offset.s
-       $(call filechk,gen-asm-offset.h)
-
-CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
-              include/asm-$(ARCH)/offset.h \
-              vmlinux.32 \
+
+CLEAN_FILES += vmlinux.32 \
               vmlinux.64 \
               vmlinux.ecoff
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
new file mode 100644 (file)
index 0000000..17b9f2f
--- /dev/null
@@ -0,0 +1,1041 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-mm1
+# Thu Sep  1 22:58:34 2005
+#
+CONFIG_MIPS=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# 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_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_NEC_CMBVR4133 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+CONFIG_TANBAC_TB022X=y
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0287=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_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_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS 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_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 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_TOSHIBA_RBTX4927 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# 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_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+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_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE 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
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=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
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ARCMSR 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA 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_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC 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)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# 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
+
+#
+# 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=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_KGDBOE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN 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 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
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_RTC_VR41XX is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_TANBAC_TB0219 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_GOTEMP is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISER4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+
+#
+# XFS support
+#
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_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_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ASFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_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_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 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_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..2c11abb
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 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 <linux/config.h>
+#include <linux/compat.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
+#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" : : "ri" (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);
+       constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
+       constant("#define _THREAD_SIZE       ", THREAD_SIZE);
+       constant("#define _THREAD_MASK       ", THREAD_MASK);
+       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_thread_fpu_defines(void)
+{
+       offset("#define THREAD_FPR0    ",
+              struct task_struct, thread.fpu.hard.fpr[0]);
+       offset("#define THREAD_FPR1    ",
+              struct task_struct, thread.fpu.hard.fpr[1]);
+       offset("#define THREAD_FPR2    ",
+              struct task_struct, thread.fpu.hard.fpr[2]);
+       offset("#define THREAD_FPR3    ",
+              struct task_struct, thread.fpu.hard.fpr[3]);
+       offset("#define THREAD_FPR4    ",
+              struct task_struct, thread.fpu.hard.fpr[4]);
+       offset("#define THREAD_FPR5    ",
+              struct task_struct, thread.fpu.hard.fpr[5]);
+       offset("#define THREAD_FPR6    ",
+              struct task_struct, thread.fpu.hard.fpr[6]);
+       offset("#define THREAD_FPR7    ",
+              struct task_struct, thread.fpu.hard.fpr[7]);
+       offset("#define THREAD_FPR8    ",
+              struct task_struct, thread.fpu.hard.fpr[8]);
+       offset("#define THREAD_FPR9    ",
+              struct task_struct, thread.fpu.hard.fpr[9]);
+       offset("#define THREAD_FPR10   ",
+              struct task_struct, thread.fpu.hard.fpr[10]);
+       offset("#define THREAD_FPR11   ",
+              struct task_struct, thread.fpu.hard.fpr[11]);
+       offset("#define THREAD_FPR12   ",
+              struct task_struct, thread.fpu.hard.fpr[12]);
+       offset("#define THREAD_FPR13   ",
+              struct task_struct, thread.fpu.hard.fpr[13]);
+       offset("#define THREAD_FPR14   ",
+              struct task_struct, thread.fpu.hard.fpr[14]);
+       offset("#define THREAD_FPR15   ",
+              struct task_struct, thread.fpu.hard.fpr[15]);
+       offset("#define THREAD_FPR16   ",
+              struct task_struct, thread.fpu.hard.fpr[16]);
+       offset("#define THREAD_FPR17   ",
+              struct task_struct, thread.fpu.hard.fpr[17]);
+       offset("#define THREAD_FPR18   ",
+              struct task_struct, thread.fpu.hard.fpr[18]);
+       offset("#define THREAD_FPR19   ",
+              struct task_struct, thread.fpu.hard.fpr[19]);
+       offset("#define THREAD_FPR20   ",
+              struct task_struct, thread.fpu.hard.fpr[20]);
+       offset("#define THREAD_FPR21   ",
+              struct task_struct, thread.fpu.hard.fpr[21]);
+       offset("#define THREAD_FPR22   ",
+              struct task_struct, thread.fpu.hard.fpr[22]);
+       offset("#define THREAD_FPR23   ",
+              struct task_struct, thread.fpu.hard.fpr[23]);
+       offset("#define THREAD_FPR24   ",
+              struct task_struct, thread.fpu.hard.fpr[24]);
+       offset("#define THREAD_FPR25   ",
+              struct task_struct, thread.fpu.hard.fpr[25]);
+       offset("#define THREAD_FPR26   ",
+              struct task_struct, thread.fpu.hard.fpr[26]);
+       offset("#define THREAD_FPR27   ",
+              struct task_struct, thread.fpu.hard.fpr[27]);
+       offset("#define THREAD_FPR28   ",
+              struct task_struct, thread.fpu.hard.fpr[28]);
+       offset("#define THREAD_FPR29   ",
+              struct task_struct, thread.fpu.hard.fpr[29]);
+       offset("#define THREAD_FPR30   ",
+              struct task_struct, thread.fpu.hard.fpr[30]);
+       offset("#define THREAD_FPR31   ",
+              struct task_struct, thread.fpu.hard.fpr[31]);
+
+       offset("#define THREAD_FCR31   ",
+              struct task_struct, thread.fpu.hard.fcr31);
+       linefeed;
+}
+
+void output_mm_defines(void)
+{
+       text("/* Size of struct page  */");
+       size("#define STRUCT_PAGE_SIZE   ", struct page);
+       linefeed;
+       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 _PAGE_SHIFT    ", PAGE_SHIFT);
+       linefeed;
+       constant("#define _PGD_T_SIZE    ", sizeof(pgd_t));
+       constant("#define _PMD_T_SIZE    ", sizeof(pmd_t));
+       constant("#define _PTE_T_SIZE    ", sizeof(pte_t));
+       linefeed;
+       constant("#define _PGD_T_LOG2    ", PGD_T_LOG2);
+       constant("#define _PMD_T_LOG2    ", PMD_T_LOG2);
+       constant("#define _PTE_T_LOG2    ", PTE_T_LOG2);
+       linefeed;
+       constant("#define _PMD_SHIFT     ", PMD_SHIFT);
+       constant("#define _PGDIR_SHIFT   ", PGDIR_SHIFT);
+       linefeed;
+       constant("#define _PGD_ORDER     ", PGD_ORDER);
+       constant("#define _PMD_ORDER     ", PMD_ORDER);
+       constant("#define _PTE_ORDER     ", PTE_ORDER);
+       linefeed;
+       constant("#define _PTRS_PER_PGD  ", PTRS_PER_PGD);
+       constant("#define _PTRS_PER_PMD  ", PTRS_PER_PMD);
+       constant("#define _PTRS_PER_PTE  ", PTRS_PER_PTE);
+       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;
+}
+
+#ifdef CONFIG_MIPS32_COMPAT
+void output_sc32_defines(void)
+{
+       text("/* Linux 32-bit sigcontext offsets. */");
+       offset("#define SC32_FPREGS     ", struct sigcontext32, sc_fpregs);
+       offset("#define SC32_FPC_CSR    ", struct sigcontext32, sc_fpc_csr);
+       offset("#define SC32_FPC_EIR    ", struct sigcontext32, sc_fpc_eir);
+       linefeed;
+}
+#endif
+
+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);
+       size("#define IC_IRQ_CPUSTAT_T   ", irq_cpustat_t);
+       linefeed;
+}
index 288bf51ad4ecd3c2da322ac3c658b39816a339b8..71416e7bbbaa380ff0be20cd167ab8065b7c8601 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/rtc.h>
 #include <asm/time.h>
 
-static spinlock_t mips_rtc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mips_rtc_lock);
 
 unsigned int get_rtc_time(struct rtc_time *time)
 {
index 7eec7568bfea593465d9958e85c452d584a7dedf..447759201d1ddb5669d3052d45f4c4a0568423b9 100644 (file)
@@ -31,7 +31,7 @@ void disable_8259A_irq(unsigned int irq);
  * moves to arch independent land
  */
 
-spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t DEFINE_SPINLOCK(i8259A_lock);
 
 static void end_8259A_irq (unsigned int irq)
 {
index 4cd3d38a22c254ce7fec677d85ca766d2986f07e..3cdc22346f4c75a69729810a668c0cb4aaafaf14 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/syscalls.h>
 #include <linux/tty.h>
 #include <linux/file.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctl.h>
@@ -33,7 +34,7 @@ static struct tty_struct *get_tty(int fd)
        struct file *filp;
        struct tty_struct *ttyp = NULL;
 
-       spin_lock(&current->files->file_lock);
+       rcu_read_lock();
        filp = fcheck(fd);
        if(filp && filp->private_data) {
                ttyp = (struct tty_struct *) filp->private_data;
@@ -41,7 +42,7 @@ static struct tty_struct *get_tty(int fd)
                if(ttyp->magic != TTY_MAGIC)
                        ttyp =NULL;
        }
-       spin_unlock(&current->files->file_lock);
+       rcu_read_unlock();
        return ttyp;
 }
 
index 4c114ae21793eb8a4fde93da5b8ba529c2222395..eff89322ba50669e77ca3b001f9139e50fde016f 100644 (file)
@@ -440,18 +440,6 @@ struct irix5_siginfo {
        } stuff;
 };
 
-static inline unsigned long timespectojiffies(struct timespec *value)
-{
-       unsigned long sec = (unsigned) value->tv_sec;
-       long nsec = value->tv_nsec;
-
-       if (sec > (LONG_MAX / HZ))
-               return LONG_MAX;
-       nsec += 1000000000L / HZ - 1;
-       nsec /= 1000000000L / HZ;
-       return HZ * sec + nsec;
-}
-
 asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
                                struct timespec *tp)
 {
@@ -489,14 +477,13 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
                        error = -EINVAL;
                        goto out;
                }
-               expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec);
+               expire = timespec_to_jiffies(tp) + (tp->tv_sec||tp->tv_nsec);
        }
 
        while(1) {
                long tmp = 0;
 
-               current->state = TASK_INTERRUPTIBLE;
-               expire = schedule_timeout(expire);
+               expire = schedule_timeout_interruptible(expire);
 
                for (i=0; i<=4; i++)
                        tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
diff --git a/arch/mips/kernel/offset.c b/arch/mips/kernel/offset.c
deleted file mode 100644 (file)
index 2c11abb..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * offset.c: Calculate pt_regs and task_struct offsets.
- *
- * Copyright (C) 1996 David S. Miller
- * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 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 <linux/config.h>
-#include <linux/compat.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-
-#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" : : "ri" (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);
-       constant("#define _THREAD_SIZE_ORDER ", THREAD_SIZE_ORDER);
-       constant("#define _THREAD_SIZE       ", THREAD_SIZE);
-       constant("#define _THREAD_MASK       ", THREAD_MASK);
-       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_thread_fpu_defines(void)
-{
-       offset("#define THREAD_FPR0    ",
-              struct task_struct, thread.fpu.hard.fpr[0]);
-       offset("#define THREAD_FPR1    ",
-              struct task_struct, thread.fpu.hard.fpr[1]);
-       offset("#define THREAD_FPR2    ",
-              struct task_struct, thread.fpu.hard.fpr[2]);
-       offset("#define THREAD_FPR3    ",
-              struct task_struct, thread.fpu.hard.fpr[3]);
-       offset("#define THREAD_FPR4    ",
-              struct task_struct, thread.fpu.hard.fpr[4]);
-       offset("#define THREAD_FPR5    ",
-              struct task_struct, thread.fpu.hard.fpr[5]);
-       offset("#define THREAD_FPR6    ",
-              struct task_struct, thread.fpu.hard.fpr[6]);
-       offset("#define THREAD_FPR7    ",
-              struct task_struct, thread.fpu.hard.fpr[7]);
-       offset("#define THREAD_FPR8    ",
-              struct task_struct, thread.fpu.hard.fpr[8]);
-       offset("#define THREAD_FPR9    ",
-              struct task_struct, thread.fpu.hard.fpr[9]);
-       offset("#define THREAD_FPR10   ",
-              struct task_struct, thread.fpu.hard.fpr[10]);
-       offset("#define THREAD_FPR11   ",
-              struct task_struct, thread.fpu.hard.fpr[11]);
-       offset("#define THREAD_FPR12   ",
-              struct task_struct, thread.fpu.hard.fpr[12]);
-       offset("#define THREAD_FPR13   ",
-              struct task_struct, thread.fpu.hard.fpr[13]);
-       offset("#define THREAD_FPR14   ",
-              struct task_struct, thread.fpu.hard.fpr[14]);
-       offset("#define THREAD_FPR15   ",
-              struct task_struct, thread.fpu.hard.fpr[15]);
-       offset("#define THREAD_FPR16   ",
-              struct task_struct, thread.fpu.hard.fpr[16]);
-       offset("#define THREAD_FPR17   ",
-              struct task_struct, thread.fpu.hard.fpr[17]);
-       offset("#define THREAD_FPR18   ",
-              struct task_struct, thread.fpu.hard.fpr[18]);
-       offset("#define THREAD_FPR19   ",
-              struct task_struct, thread.fpu.hard.fpr[19]);
-       offset("#define THREAD_FPR20   ",
-              struct task_struct, thread.fpu.hard.fpr[20]);
-       offset("#define THREAD_FPR21   ",
-              struct task_struct, thread.fpu.hard.fpr[21]);
-       offset("#define THREAD_FPR22   ",
-              struct task_struct, thread.fpu.hard.fpr[22]);
-       offset("#define THREAD_FPR23   ",
-              struct task_struct, thread.fpu.hard.fpr[23]);
-       offset("#define THREAD_FPR24   ",
-              struct task_struct, thread.fpu.hard.fpr[24]);
-       offset("#define THREAD_FPR25   ",
-              struct task_struct, thread.fpu.hard.fpr[25]);
-       offset("#define THREAD_FPR26   ",
-              struct task_struct, thread.fpu.hard.fpr[26]);
-       offset("#define THREAD_FPR27   ",
-              struct task_struct, thread.fpu.hard.fpr[27]);
-       offset("#define THREAD_FPR28   ",
-              struct task_struct, thread.fpu.hard.fpr[28]);
-       offset("#define THREAD_FPR29   ",
-              struct task_struct, thread.fpu.hard.fpr[29]);
-       offset("#define THREAD_FPR30   ",
-              struct task_struct, thread.fpu.hard.fpr[30]);
-       offset("#define THREAD_FPR31   ",
-              struct task_struct, thread.fpu.hard.fpr[31]);
-
-       offset("#define THREAD_FCR31   ",
-              struct task_struct, thread.fpu.hard.fcr31);
-       linefeed;
-}
-
-void output_mm_defines(void)
-{
-       text("/* Size of struct page  */");
-       size("#define STRUCT_PAGE_SIZE   ", struct page);
-       linefeed;
-       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 _PAGE_SHIFT    ", PAGE_SHIFT);
-       linefeed;
-       constant("#define _PGD_T_SIZE    ", sizeof(pgd_t));
-       constant("#define _PMD_T_SIZE    ", sizeof(pmd_t));
-       constant("#define _PTE_T_SIZE    ", sizeof(pte_t));
-       linefeed;
-       constant("#define _PGD_T_LOG2    ", PGD_T_LOG2);
-       constant("#define _PMD_T_LOG2    ", PMD_T_LOG2);
-       constant("#define _PTE_T_LOG2    ", PTE_T_LOG2);
-       linefeed;
-       constant("#define _PMD_SHIFT     ", PMD_SHIFT);
-       constant("#define _PGDIR_SHIFT   ", PGDIR_SHIFT);
-       linefeed;
-       constant("#define _PGD_ORDER     ", PGD_ORDER);
-       constant("#define _PMD_ORDER     ", PMD_ORDER);
-       constant("#define _PTE_ORDER     ", PTE_ORDER);
-       linefeed;
-       constant("#define _PTRS_PER_PGD  ", PTRS_PER_PGD);
-       constant("#define _PTRS_PER_PMD  ", PTRS_PER_PMD);
-       constant("#define _PTRS_PER_PTE  ", PTRS_PER_PTE);
-       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;
-}
-
-#ifdef CONFIG_MIPS32_COMPAT
-void output_sc32_defines(void)
-{
-       text("/* Linux 32-bit sigcontext offsets. */");
-       offset("#define SC32_FPREGS     ", struct sigcontext32, sc_fpregs);
-       offset("#define SC32_FPC_CSR    ", struct sigcontext32, sc_fpc_csr);
-       offset("#define SC32_FPC_EIR    ", struct sigcontext32, sc_fpc_eir);
-       linefeed;
-}
-#endif
-
-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);
-       size("#define IC_IRQ_CPUSTAT_T   ", irq_cpustat_t);
-       linefeed;
-}
index f83c31f720c4d67efeb86008bc917644f3924712..ac68e68339db6957c63a322a62ed93fa6b381152 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/errno.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define EX(a,b)                                                        \
index f10019640ee997847d1e7548cd4971efb5afd437..0d9c4a32a9c2dbc617fb727dd67f9d00bc509718 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/cachectl.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
index aba665bcb3864e22b73c69f4ec7c94ae39199d29..1a14c6b18829992afb2d16a08988ae83bd608f89 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/errno.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
        .macro  EX insn, reg, src
index e02b7722ccb8d1753e073bf85eb08b18849f7f8f..d2afbd19a9c8a0c013b4170008d55a18d701e61c 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/cachectl.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/regdef.h>
index d8d3b13fe57ffa7c1a037e9d8d6afd8bcaeb7185..43cda53f5af6866db959d054c2b8fea2b4e46077 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
        .set    noreorder
index 344f2e29eb616816da5cf0de6ed95a219f6d6958..17b5030fb6ea2db5eb4749cb7ae9c93a3ed66258 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 #include <asm/war.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 
 /* Highest syscall used of any syscall flavour */
 #define MAX_SYSCALL_NO __NR_O32_Linux + __NR_O32_Linux_syscalls
index 32efb888160abf7ffb245ab6720f3bc8c0dcb1ec..ffb22a2068bf960a95291b7063ca83424ee44f43 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/sysmips.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
index ae2a1312d4efe1e06f98fa999b1029fbffa8517a..21e3e13a4b4466386636a8fa571e18ed5495eabb 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/cachectl.h>
 #include <asm/cacheflush.h>
 #include <asm/ipc.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/signal.h>
 #include <asm/sim.h>
 #include <asm/shmparam.h>
index b4659546271789c6498967d40f81bb68e7283f83..4de155699c4fa2d748267365c923b6a1eaf2a58a 100644 (file)
@@ -1032,8 +1032,7 @@ bad:
 
 asmlinkage int irix_sginap(int ticks)
 {
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(ticks);
+       schedule_timeout_interruptible(ticks);
        return 0;
 }
 
index ad9ff4071ce9238f208efd82a1e7f05cc77dec45..1981485bd48b7f34120d0a70aa1fb4dcc74e5d3c 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)                      \
index 242f1976cfaf097e504a1ce86e207a3300deab03..e2c42c85113b32b3fbd460b6ed58281df275067d 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)                      \
index e44e9579bd36dcce1f2f1a80e5594f95788612e4..fd82c84a93b726d318411fe8c0967c71b12e8c50 100644 (file)
  * has a cmpxchg, and where atomic->value is an int holding
  * the value of the atomic (i.e. the high bits aren't used
  * for a lock or anything like that).
- *
- * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
- * if spinlocks are empty and thus atomic_dec_and_lock is defined
- * to be atomic_dec_and_test - in that case we don't need it
- * defined here as well.
  */
-
-#ifndef ATOMIC_DEC_AND_LOCK
 int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 {
        int counter;
@@ -52,4 +45,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 }
 
 EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif /* ATOMIC_DEC_AND_LOCK */
index 90ee8d43261f591d2f509bf10ae7c6981e6bc3b5..a78865f76547848d3cc1a1b495e6a6360dfc79ff 100644 (file)
@@ -14,7 +14,7 @@
  */
 #include <linux/config.h>
 #include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define dst a0
index 07660e86c99dadf8a4a3981c91481420ee68e9e9..eca558d83a3730e7fe83890cb2144e1ab792495f 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1999 Silicon Graphics, Inc.
  */
 #include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)                      \
index 14bed17c1648a70d178238c5f465fee4be97a9a3..d16c76fbfac721c5cdaf20d33628c948ca83571c 100644 (file)
@@ -7,7 +7,7 @@
  */
 #include <linux/errno.h>
 #include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)                      \
index 6e7a8eed4de8f222ef61ee296f1c8d5b46144056..c0ea15194a0e8d132979de4a0ad02ab6e9cf9378 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1999 Silicon Graphics, Inc.
  */
 #include <asm/asm.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
 #define EX(insn,reg,addr,handler)                      \
index c53e4cb359ba759b766c6fc253b168535e0eaf00..83d81c9cdc2b3c58299f5fd4fa46095090676523 100644 (file)
@@ -48,6 +48,7 @@ obj-$(CONFIG_SIBYTE_SB1250)   += fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SNI_RM200_PCI)    += fixup-sni.o ops-sni.o
 obj-$(CONFIG_TANBAC_TB0219)    += fixup-tb0219.o
 obj-$(CONFIG_TANBAC_TB0226)    += fixup-tb0226.o
+obj-$(CONFIG_TANBAC_TB0287)    += fixup-tb0287.o
 obj-$(CONFIG_TOSHIBA_JMR3927)  += fixup-jmr3927.o pci-jmr3927.o
 obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o
 obj-$(CONFIG_VICTOR_MPC30X)    += fixup-mpc30x.o
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
new file mode 100644 (file)
index 0000000..8436d7f
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups.
+ *
+ *  Copyright (C) 2005  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.
+ *
+ *  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 <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/tb0287.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       unsigned char bus;
+       int irq = -1;
+
+       bus = dev->bus->number;
+       if (bus == 0) {
+               switch (slot) {
+               case 16:
+                       irq = TB0287_SM501_IRQ;
+                       break;
+               case 17:
+                       irq = TB0287_SIL680A_IRQ;
+                       break;
+               default:
+                       break;
+               }
+       } else if (bus == 1) {
+               switch (PCI_SLOT(dev->devfn)) {
+               case 0:
+                       irq = TB0287_PCI_SLOT_IRQ;
+                       break;
+               case 2:
+               case 3:
+                       irq = TB0287_RTL8110_IRQ;
+                       break;
+               default:
+                       break;
+               }
+       } else if (bus > 1) {
+               irq = TB0287_PCI_SLOT_IRQ;
+       }
+
+       return irq;
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       return 0;
+}
index 0403d2fcb85ef62fa9eeee413ed586062de6da9f..3b339b1cce137d9dd5322e07c1e3d2b5678d3149 100644 (file)
@@ -100,15 +100,7 @@ kernel_install: vmlinux
 
 install: kernel_install modules_install
 
-prepare: include/asm-parisc/offsets.h
-
-arch/parisc/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-parisc/offsets.h: arch/parisc/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES    += lifimage include/asm-parisc/offsets.h
+CLEAN_FILES    += lifimage
 MRPROPER_FILES += palo.conf
 
 define archhelp
index 2680a1c0fa7742dd0b23652bdf09fc58e7e710a5..aaaf3306c05acaff2cf87a07a5e5fcf9de0f3c05 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #include <asm/assembly.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
 
index 1aa936dfe1476fc0f2b6072174bff329dc5ce29a..0b0c3a66b1becfbf4bc09be41087317ed7869647 100644 (file)
@@ -24,7 +24,7 @@
 #warning PA64 support needs more work...did first cut
 #endif
 
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/assembly.h>
 #include <asm/signal.h>
 
index ee58d37dbb2753fe64ada15978e6b056c60cf00d..be0f07f2fa5846f62551d2143417f8a0d1e719ac 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #include <linux/config.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 /* we have the following possibilities to act on an interruption:
  *  - handle in assembly and use shadowed registers only
index ddf7e914f15e0aedae4a50443f0a8aeb95fb82b7..28405edf844887816931ac90fd3c01fbe1e0f259 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <linux/autoconf.h>    /* for CONFIG_SMP */
 
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/psw.h>
 #include <asm/pdc.h>
        
index 4fc04501d5e5d9c9752d7573b47775cfdc4cd539..46b759385115afd636a77a6e2b4a228581ad6ba9 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/kallsyms.h>
 
 #include <asm/io.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/pdc.h>
 #include <asm/pdc_chassis.h>
 #include <asm/pgalloc.h>
index c07db9dff7cd8604980b00fd2e8e5bf78e4dcc57..f3428e5e86fb9fd25c2148d5c37c5fb390ea2a39 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/processor.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 /* PSW bits we allow the debugger to modify */
 #define USER_PSW_BITS  (PSW_N | PSW_V | PSW_CB)
index 55d71c15e1f7cebc25b68c9e9facb4c7fdfb69e4..0224651fd8f1547e298ab6669ae26f6bebb3cc79 100644 (file)
@@ -32,7 +32,7 @@
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
index 32ea701f4d2015d9a80ca2a2ccda7f58799d087e..8c7a7185cd3b0ebd2e73d0b1909dcf8000c98892 100644 (file)
@@ -7,7 +7,7 @@
  * sorry about the wall, puffin..
  */
 
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/psw.h>
index 7bf705676297a424af3f35dda2787224bce46f7c..5f2e6904d14aecb897773538b1eadd001fde93f5 100644 (file)
@@ -5,5 +5,3 @@
 lib-y  := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
 
 obj-y  := iomap.o
-
-lib-$(CONFIG_SMP) += debuglocks.o
index 2de182f6fe8a9eb2077404de6ed71bd65d00010a..90f400b10282276b12eb5fba16ea14c6c61ff449 100644 (file)
@@ -13,8 +13,8 @@
 #include <asm/atomic.h>
 
 #ifdef CONFIG_SMP
-spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
-       [0 ... (ATOMIC_HASH_SIZE-1)]  = SPIN_LOCK_UNLOCKED
+raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
+       [0 ... (ATOMIC_HASH_SIZE-1)]  = __RAW_SPIN_LOCK_UNLOCKED
 };
 #endif
 
diff --git a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
deleted file mode 100644 (file)
index 1b33fe6..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/* 
- *    Debugging versions of SMP locking primitives.
- *
- *    Copyright (C) 2004 Thibaut VARENE <varenet@parisc-linux.org>
- *
- *    Some code stollen from alpha & sparc64 ;)
- *
- *    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
- *
- *    We use pdc_printf() throughout the file for all output messages, to avoid
- *    losing messages because of disabled interrupts. Since we're using these
- *    messages for debugging purposes, it makes sense not to send them to the
- *    linux console.
- */
-
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/hardirq.h>     /* in_interrupt() */
-#include <asm/system.h>
-#include <asm/hardirq.h>       /* in_interrupt() */
-#include <asm/pdc.h>
-
-#undef INIT_STUCK
-#define INIT_STUCK 1L << 30
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-
-
-void _dbg_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
-{
-       volatile unsigned int *a;
-       long stuck = INIT_STUCK;
-       void *inline_pc = __builtin_return_address(0);
-       unsigned long started = jiffies;
-       int printed = 0;
-       int cpu = smp_processor_id();
-
-try_again:
-
-       /* Do the actual locking */
-       /* <T-Bone> ggg: we can't get stuck on the outter loop?
-        * <ggg> T-Bone: We can hit the outer loop
-        *      alot if multiple CPUs are constantly racing for a lock
-        *      and the backplane is NOT fair about which CPU sees
-        *      the update first. But it won't hang since every failed
-        *      attempt will drop us back into the inner loop and
-        *      decrement `stuck'.
-        * <ggg> K-class and some of the others are NOT fair in the HW
-        *      implementation so we could see false positives.
-        *      But fixing the lock contention is easier than
-        *      fixing the HW to be fair.
-        * <tausq> __ldcw() returns 1 if we get the lock; otherwise we
-        *      spin until the value of the lock changes, or we time out.
-        */
-       mb();
-       a = __ldcw_align(lock);
-       while (stuck && (__ldcw(a) == 0))
-               while ((*a == 0) && --stuck);
-       mb();
-
-       if (unlikely(stuck <= 0)) {
-               pdc_printf(
-                       "%s:%d: spin_lock(%s/%p) stuck in %s at %p(%d)"
-                       " owned by %s:%d in %s at %p(%d)\n",
-                       base_file, line_no, lock->module, lock,
-                       current->comm, inline_pc, cpu,
-                       lock->bfile, lock->bline, lock->task->comm,
-                       lock->previous, lock->oncpu);
-               stuck = INIT_STUCK;
-               printed = 1;
-               goto try_again;
-       }
-
-       /* Exiting.  Got the lock.  */
-       lock->oncpu = cpu;
-       lock->previous = inline_pc;
-       lock->task = current;
-       lock->bfile = (char *)base_file;
-       lock->bline = line_no;
-
-       if (unlikely(printed)) {
-               pdc_printf(
-                       "%s:%d: spin_lock grabbed in %s at %p(%d) %ld ticks\n",
-                       base_file, line_no, current->comm, inline_pc,
-                       cpu, jiffies - started);
-       }
-}
-
-void _dbg_spin_unlock(spinlock_t * lock, const char *base_file, int line_no)
-{
-       CHECK_LOCK(lock);
-       volatile unsigned int *a;
-       mb();
-       a = __ldcw_align(lock);
-       if (unlikely((*a != 0) && lock->babble)) {
-               lock->babble--;
-               pdc_printf(
-                       "%s:%d: spin_unlock(%s:%p) not locked\n",
-                       base_file, line_no, lock->module, lock);
-       }
-       *a = 1; 
-       mb();
-}
-
-int _dbg_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
-{
-       int ret;
-       volatile unsigned int *a;
-       mb();
-       a = __ldcw_align(lock);
-       ret = (__ldcw(a) != 0);
-       mb();
-       if (ret) {
-               lock->oncpu = smp_processor_id();
-               lock->previous = __builtin_return_address(0);
-               lock->task = current;
-       } else {
-               lock->bfile = (char *)base_file;
-               lock->bline = line_no;
-       }
-       return ret;
-}
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#ifdef CONFIG_DEBUG_RWLOCK
-
-/* Interrupts trouble detailed explanation, thx Grant:
- *
- * o writer (wants to modify data) attempts to acquire the rwlock
- * o He gets the write lock.
- * o Interupts are still enabled, we take an interrupt with the
- *   write still holding the lock.
- * o interrupt handler tries to acquire the rwlock for read.
- * o deadlock since the writer can't release it at this point.
- * 
- * In general, any use of spinlocks that competes between "base"
- * level and interrupt level code will risk deadlock. Interrupts
- * need to be disabled in the base level routines to avoid it.
- * Or more precisely, only the IRQ the base level routine
- * is competing with for the lock.  But it's more efficient/faster
- * to just disable all interrupts on that CPU to guarantee
- * once it gets the lock it can release it quickly too.
- */
-void _dbg_write_lock(rwlock_t *rw, const char *bfile, int bline)
-{
-       void *inline_pc = __builtin_return_address(0);
-       unsigned long started = jiffies;
-       long stuck = INIT_STUCK;
-       int printed = 0;
-       int cpu = smp_processor_id();
-       
-       if(unlikely(in_interrupt())) {  /* acquiring write lock in interrupt context, bad idea */
-               pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
-               BUG();
-       }
-
-       /* Note: if interrupts are disabled (which is most likely), the printk
-       will never show on the console. We might need a polling method to flush
-       the dmesg buffer anyhow. */
-       
-retry:
-       _raw_spin_lock(&rw->lock);
-
-       if(rw->counter != 0) {
-               /* this basically never happens */
-               _raw_spin_unlock(&rw->lock);
-               
-               stuck--;
-               if ((unlikely(stuck <= 0)) && (rw->counter < 0)) {
-                       pdc_printf(
-                               "%s:%d: write_lock stuck on writer"
-                               " in %s at %p(%d) %ld ticks\n",
-                               bfile, bline, current->comm, inline_pc,
-                               cpu, jiffies - started);
-                       stuck = INIT_STUCK;
-                       printed = 1;
-               }
-               else if (unlikely(stuck <= 0)) {
-                       pdc_printf(
-                               "%s:%d: write_lock stuck on reader"
-                               " in %s at %p(%d) %ld ticks\n",
-                               bfile, bline, current->comm, inline_pc,
-                               cpu, jiffies - started);
-                       stuck = INIT_STUCK;
-                       printed = 1;
-               }
-               
-               while(rw->counter != 0);
-
-               goto retry;
-       }
-
-       /* got it.  now leave without unlocking */
-       rw->counter = -1; /* remember we are locked */
-
-       if (unlikely(printed)) {
-               pdc_printf(
-                       "%s:%d: write_lock grabbed in %s at %p(%d) %ld ticks\n",
-                       bfile, bline, current->comm, inline_pc,
-                       cpu, jiffies - started);
-       }
-}
-
-int _dbg_write_trylock(rwlock_t *rw, const char *bfile, int bline)
-{
-#if 0
-       void *inline_pc = __builtin_return_address(0);
-       int cpu = smp_processor_id();
-#endif
-       
-       if(unlikely(in_interrupt())) {  /* acquiring write lock in interrupt context, bad idea */
-               pdc_printf("write_lock caller: %s:%d, IRQs enabled,\n", bfile, bline);
-               BUG();
-       }
-
-       /* Note: if interrupts are disabled (which is most likely), the printk
-       will never show on the console. We might need a polling method to flush
-       the dmesg buffer anyhow. */
-       
-       _raw_spin_lock(&rw->lock);
-
-       if(rw->counter != 0) {
-               /* this basically never happens */
-               _raw_spin_unlock(&rw->lock);
-               return 0;
-       }
-
-       /* got it.  now leave without unlocking */
-       rw->counter = -1; /* remember we are locked */
-#if 0
-       pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
-                  bfile, bline, current->comm, inline_pc, cpu);
-#endif
-       return 1;
-}
-
-void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
-{
-#if 0
-       void *inline_pc = __builtin_return_address(0);
-       unsigned long started = jiffies;
-       int cpu = smp_processor_id();
-#endif
-       unsigned long flags;
-
-       local_irq_save(flags);
-       _raw_spin_lock(&rw->lock); 
-
-       rw->counter++;
-#if 0
-       pdc_printf(
-               "%s:%d: read_lock grabbed in %s at %p(%d) %ld ticks\n",
-               bfile, bline, current->comm, inline_pc,
-               cpu, jiffies - started);
-#endif
-       _raw_spin_unlock(&rw->lock);
-       local_irq_restore(flags);
-}
-
-#endif /* CONFIG_DEBUG_RWLOCK */
index 134f0cd240f555409c8be23ea98470c45f18d7e9..1b91612ed964ef79507039faea61ac3c7e50465b 100644 (file)
@@ -20,7 +20,7 @@
  * Fixup routines for kernel exception handling.
  */
 #include <linux/config.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/assembly.h>
 #include <asm/errno.h>
 
index 89fe0ceeaa40294dfacdffc15590af7f5623e299..2ca9ec7ec3a7b4d161be57bf48f5dd3d76c18773 100644 (file)
@@ -1380,7 +1380,7 @@ static void cs_nosound(unsigned long xx)
        spin_unlock_irqrestore(&cs4218_lock, flags);
 }
 
-static struct timer_list beep_timer = TIMER_INITIALIZER(cs_nosound, 0, 0);
+static DEFINE_TIMER(beep_timer, cs_nosound, 0, 0);
 };
 
 static void cs_mksound(unsigned int hz, unsigned int ticks)
index 6ab7e5ea5fcfd9e0ae748d83bde3f31f158fa25b..347ea284140b28be32262dbb0427af539845940b 100644 (file)
@@ -265,6 +265,15 @@ config PPC601_SYNC_FIX
 
          If in doubt, say Y here.
 
+config HOTPLUG_CPU
+       bool "Support for enabling/disabling CPUs"
+       depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PMAC
+       ---help---
+         Say Y here to be able to disable and re-enable individual
+         CPUs at runtime on SMP machines.
+
+         Say N if you are unsure.
+
 source arch/ppc/platforms/4xx/Kconfig
 source arch/ppc/platforms/85xx/Kconfig
 
@@ -499,11 +508,6 @@ config WINCEPT
          MPC821 PowerPC, introduced in 1998 and designed to be used in
          thin-client machines.  Say Y to support it directly.
 
-         Be aware that PCI buses can only function when SYS board is plugged
-         into the PIB (Platform IO Board) board from Freescale which provide
-         3 PCI slots.  The PIBs PCI initialization is the bootloader's
-         responsiblilty.
-
 endchoice
 
 choice
@@ -680,6 +684,11 @@ config MPC834x_SYS
        help
          This option enables support for the MPC 834x SYS evaluation board.
 
+         Be aware that PCI buses can only function when SYS board is plugged
+         into the PIB (Platform IO Board) board from Freescale which provide
+         3 PCI slots.  The PIBs PCI initialization is the bootloader's
+         responsiblilty.
+
 config EV64360
        bool "Marvell-EV64360BP"
        help
index d1b6e6dcb50414af2ca4fe38ab3f463bd2a8ded5..16e2675f3270b3c39acde78139cfc2cc4f98fabf 100644 (file)
@@ -21,13 +21,14 @@ CC          := $(CC) -m32
 endif
 
 LDFLAGS_vmlinux        := -Ttext $(KERNELLOAD) -Bstatic
-CPPFLAGS       += -Iarch/$(ARCH) -Iinclude3
+# The -Iarch/$(ARCH)/include is temporary while we are merging
+CPPFLAGS       += -Iarch/$(ARCH) -Iarch/$(ARCH)/include
 AFLAGS         += -Iarch/$(ARCH)
 CFLAGS         += -Iarch/$(ARCH) -msoft-float -pipe \
                -ffixed-r2 -mmultiple
 CPP            = $(CC) -E $(CFLAGS)
 # Temporary hack until we have migrated to asm-powerpc
-LINUXINCLUDE    += -Iinclude3
+LINUXINCLUDE    += -Iarch/$(ARCH)/include
 
 CHECKFLAGS     += -D__powerpc__
 
@@ -103,21 +104,16 @@ endef
 
 archclean:
        $(Q)$(MAKE) $(clean)=arch/ppc/boot
-       $(Q)rm -rf include3
+       # Temporary hack until we have migrated to asm-powerpc
+       $(Q)rm -rf arch/$(ARCH)/include
 
-prepare: include/asm-$(ARCH)/offsets.h checkbin
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
+archprepare: checkbin
 
 # Temporary hack until we have migrated to asm-powerpc
-include/asm: include3/asm
-include3/asm:
-       $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi
-       $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm
+include/asm: arch/$(ARCH)/include/asm
+arch/$(ARCH)/include/asm:
+       $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi
+       $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm
 
 # Use the file '.tmp_gas_check' for binutils tests, as gas won't output
 # to stdout and these checks are run even on install targets.
@@ -143,7 +139,5 @@ checkbin:
                false ; \
        fi
 
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h \
-               arch/$(ARCH)/kernel/asm-offsets.s \
-               $(TOUT)
+CLEAN_FILES += $(TOUT)
 
index 9017c547a6f6fe8c073403e908182c7b621bd56f..26818bbb6cfff6fe14657415f0899d957780ebc0 100644 (file)
@@ -23,7 +23,7 @@ static int shift;
 
 unsigned long serial_init(int chan, void *ignored)
 {
-       unsigned long com_port;
+       unsigned long com_port, base_baud;
        unsigned char lcr, dlm;
 
        /* We need to find out which type io we're expecting.  If it's
@@ -43,6 +43,8 @@ unsigned long serial_init(int chan, void *ignored)
 
        /* How far apart the registers are. */
        shift = rs_table[chan].iomem_reg_shift;
+       /* Base baud.. */
+       base_baud = rs_table[chan].baud_base;
        
        /* save the LCR */
        lcr = inb(com_port + (UART_LCR << shift));
@@ -62,9 +64,9 @@ unsigned long serial_init(int chan, void *ignored)
        else {
                /* Input clock. */
                outb(com_port + (UART_DLL << shift),
-                    (BASE_BAUD / SERIAL_BAUD) & 0xFF);
+                    (base_baud / SERIAL_BAUD) & 0xFF);
                outb(com_port + (UART_DLM << shift),
-                    (BASE_BAUD / SERIAL_BAUD) >> 8);
+                    (base_baud / SERIAL_BAUD) >> 8);
                /* 8 data, 1 stop, no parity */
                outb(com_port + (UART_LCR << shift), 0x03);
                /* RTS/DTR */
index 47e641455bc59d8e6bcf3023bc6e64ddc2c667fa..c96c9f80521ec13dd974d0d96c7629a886d181db 100644 (file)
@@ -252,7 +252,7 @@ _GLOBAL(flush_instruction_cache)
 1:     dcbf    r0,r3                   # Flush the data cache
        icbi    r0,r3                   # Invalidate the instruction cache
        addi    r3,r3,0x10              # Increment by one cache line
-       cmplwi  cr0,r3,r4               # Are we at the end yet?
+       cmplw   cr0,r3,r4               # Are we at the end yet?
        blt     1b                      # No, keep flushing and invalidating
 #else
        /* Enable, invalidate and then disable the L1 icache/dcache. */
index b1457a8a9c0f0eff8cf3cf130396076438d8d7e5..1fb92f16acd61efba7b3a1c641c13e485523b6d7 100644 (file)
@@ -15,8 +15,9 @@ extra-y                               += vmlinux.lds
 obj-y                          := entry.o traps.o irq.o idle.o time.o misc.o \
                                        process.o signal.o ptrace.o align.o \
                                        semaphore.o syscalls.o setup.o \
-                                       cputable.o ppc_htab.o perfmon.o
+                                       cputable.o ppc_htab.o
 obj-$(CONFIG_6xx)              += l2cr.o cpu_setup_6xx.o
+obj-$(CONFIG_E500)             += perfmon.o
 obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
 obj-$(CONFIG_POWER4)           += cpu_setup_power4.o
 obj-$(CONFIG_MODULES)          += module.o ppc_ksyms.o
index bd037caa40559e0e79409e7ac9d5a4130ee32afd..ba396438ede34ff1c7b555f95b7c1dee9e3429d3 100644 (file)
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <asm/ppc_asm.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
 _GLOBAL(__setup_cpu_601)
index f2ea1a990f170379a2700166152afba359209d2b..7e4fbb65372405d5d22482197518436859f3e6f9 100644 (file)
@@ -14,8 +14,7 @@
 #include <asm/page.h>
 #include <asm/ppc_asm.h>
 #include <asm/cputable.h>
-#include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
 _GLOBAL(__970_cpu_preinit)
index e0c631cf96b039429a24c609284c9531bef076c8..b566d982806c937ba8ca7e55c01b007a32777477 100644 (file)
@@ -393,7 +393,7 @@ EXPORT_SYMBOL(__dma_sync);
  * __dma_sync_page() implementation for systems using highmem.
  * In this case, each page of a buffer must be kmapped/kunmapped
  * in order to have a virtual address for __dma_sync(). This must
- * not sleep so kmap_atmomic()/kunmap_atomic() are used.
+ * not sleep so kmap_atomic()/kunmap_atomic() are used.
  *
  * Note: yes, it is possible and correct to have a buffer extend
  * beyond the first page.
index cb83045e2edfb6408cf88a2b4e58f921d7d6ec53..03d4886869f3ebea83cbf95e9f0d81381fa44883 100644 (file)
@@ -29,7 +29,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 
 #undef SHOW_SYSCALLS
index 6189b26f640f28ece1408e5393258fb3d97d461e..665d7d34304cd0118c62c18963600ddbb8070118 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 /*
  * This task wants to use the FPU now.
index a931d773715fa218b50a5496dc4d07e978244219..1960fb8c259c6e268c270ac716c3498302279784 100644 (file)
@@ -31,7 +31,7 @@
 #include <asm/cache.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
@@ -1023,23 +1023,21 @@ __secondary_start_gemini:
         andc    r4,r4,r3
         mtspr   SPRN_HID0,r4
         sync
-        bl      gemini_prom_init
         b       __secondary_start
 #endif /* CONFIG_GEMINI */
-       .globl  __secondary_start_psurge
-__secondary_start_psurge:
-       li      r24,1                   /* cpu # */
-       b       __secondary_start_psurge99
-       .globl  __secondary_start_psurge2
-__secondary_start_psurge2:
-       li      r24,2                   /* cpu # */
-       b       __secondary_start_psurge99
-       .globl  __secondary_start_psurge3
-__secondary_start_psurge3:
-       li      r24,3                   /* cpu # */
-       b       __secondary_start_psurge99
-__secondary_start_psurge99:
-       /* we come in here with IR=0 and DR=1, and DBAT 0
+
+       .globl  __secondary_start_pmac_0
+__secondary_start_pmac_0:
+       /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
+       li      r24,0
+       b       1f
+       li      r24,1
+       b       1f
+       li      r24,2
+       b       1f
+       li      r24,3
+1:
+       /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0
           set to map the 0xf0000000 - 0xffffffff region */
        mfmsr   r0
        rlwinm  r0,r0,0,28,26           /* clear DR (0x10) */
index 9e68e32edb6065a25a9d90a2710ee1cd61b26c7b..599245b0407ed44d89def0d910bd9dff449f544e 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include "head_booke.h"
 
 
index ca9518b96c6ebe54ec0df5823b900336203ef8c6..8562b807b37c2087167abc6b259305b90f5525cf 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
index eb18cadb3755b7f13bec77fd64c4cf4c2e2a79e3..cb1a3a54a02641c0e87e313d639d4b0630ba39d9 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 /* Macro to make the code more readable. */
 #ifdef CONFIG_8xx_CPU6
index 4028f4c7d97893f0e6785c032f5f469282f30b72..8e52e840831617638afbb9fa81005c743e0d9d80 100644 (file)
@@ -41,7 +41,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include "head_booke.h"
 
 /* As with the other PowerPC ports, it is expected that when code
index 53547b6de45bd491e96c0444907b74b36915592c..fba29c876b62ab843d06e308ef2590c9f3999f85 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
+#include <linux/cpu.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -35,6 +36,7 @@
 void default_idle(void)
 {
        void (*powersave)(void);
+       int cpu = smp_processor_id();
 
        powersave = ppc_md.power_save;
 
@@ -44,7 +46,7 @@ void default_idle(void)
 #ifdef CONFIG_SMP
                else {
                        set_thread_flag(TIF_POLLING_NRFLAG);
-                       while (!need_resched())
+                       while (!need_resched() && !cpu_is_offline(cpu))
                                barrier();
                        clear_thread_flag(TIF_POLLING_NRFLAG);
                }
@@ -52,6 +54,8 @@ void default_idle(void)
        }
        if (need_resched())
                schedule();
+       if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
+               cpu_die();
 }
 
 /*
index 25d009c75f7bc0e3bfe4aba34679c94727d2d403..1a2194cf68281c817794b6fd6c15e45fd96e9b28 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #undef DEBUG
 
index 73a58ff03900a00eb66916466683a2a1eb7879f9..cc0d535365cdb53b362b2177bd6ac5de325eb5db 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #undef DEBUG
 
index ce71b4a0158595b6d20791cb72dc0f4d932290f9..90d917d2e856fed7cb98517643fcd9827ec9b5f6 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/mmu.h>
 #include <asm/ppc_asm.h>
 #include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
 
index e70b587b9e514ae39b80ca70a2601ea7776fdb62..726fe7ce1747ae004570f9c6e05766907a89d4bb 100644 (file)
@@ -45,6 +45,7 @@ cpumask_t cpu_online_map;
 cpumask_t cpu_possible_map;
 int smp_hw_index[NR_CPUS];
 struct thread_info *secondary_ti;
+static struct task_struct *idle_tasks[NR_CPUS];
 
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
@@ -286,7 +287,8 @@ static void __devinit smp_store_cpu_info(int id)
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-       int num_cpus, i;
+       int num_cpus, i, cpu;
+       struct task_struct *p;
 
        /* Fixup boot cpu */
         smp_store_cpu_info(smp_processor_id());
@@ -308,6 +310,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 
        if (smp_ops->space_timers)
                smp_ops->space_timers(num_cpus);
+
+       for_each_cpu(cpu) {
+               if (cpu == smp_processor_id())
+                       continue;
+               /* create a process for the processor */
+               p = fork_idle(cpu);
+               if (IS_ERR(p))
+                       panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
+               p->thread_info->cpu = cpu;
+               idle_tasks[cpu] = p;
+       }
 }
 
 void __devinit smp_prepare_boot_cpu(void)
@@ -334,12 +347,17 @@ int __devinit start_secondary(void *unused)
        set_dec(tb_ticks_per_jiffy);
        cpu_callin_map[cpu] = 1;
 
-       printk("CPU %i done callin...\n", cpu);
+       printk("CPU %d done callin...\n", cpu);
        smp_ops->setup_cpu(cpu);
-       printk("CPU %i done setup...\n", cpu);
-       local_irq_enable();
+       printk("CPU %d done setup...\n", cpu);
        smp_ops->take_timebase();
-       printk("CPU %i done timebase take...\n", cpu);
+       printk("CPU %d done timebase take...\n", cpu);
+
+       spin_lock(&call_lock);
+       cpu_set(cpu, cpu_online_map);
+       spin_unlock(&call_lock);
+
+       local_irq_enable();
 
        cpu_idle();
        return 0;
@@ -347,17 +365,11 @@ int __devinit start_secondary(void *unused)
 
 int __cpu_up(unsigned int cpu)
 {
-       struct task_struct *p;
        char buf[32];
        int c;
 
-       /* create a process for the processor */
-       /* only regs.msr is actually used, and 0 is OK for it */
-       p = fork_idle(cpu);
-       if (IS_ERR(p))
-               panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-       secondary_ti = p->thread_info;
-       p->thread_info->cpu = cpu;
+       secondary_ti = idle_tasks[cpu]->thread_info;
+       mb();
 
        /*
         * There was a cache flush loop here to flush the cache
@@ -389,7 +401,11 @@ int __cpu_up(unsigned int cpu)
        printk("Processor %d found.\n", cpu);
 
        smp_ops->give_timebase();
-       cpu_set(cpu, cpu_online_map);
+
+       /* Wait until cpu puts itself in the online map */
+       while (!cpu_online(cpu))
+               cpu_relax();
+
        return 0;
 }
 
index 55148bb88d39983bafa3251cc3a85666a45b80af..69773cc1a85f35a39b9914d17765e5ae513a6adf 100644 (file)
@@ -5,7 +5,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 
 /*
index d87423d1003a6c1de89d4880aff8aa17c889a1c9..961ede87be72254f421d6f2f269668bb19f54070 100644 (file)
@@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
        info.si_code = code;
        info.si_addr = (void __user *) addr;
        force_sig_info(signr, &info, current);
+
+       /*
+        * Init gets no signals that it doesn't have a handler for.
+        * That's all very well, but if it has caused a synchronous
+        * exception and we ignore the resulting signal, it will just
+        * generate the same exception over and over again and we get
+        * nowhere.  Better to kill it and let the kernel panic.
+        */
+       if (current->pid == 1) {
+               __sighandler_t handler;
+
+               spin_lock_irq(&current->sighand->siglock);
+               handler = current->sighand->action[signr-1].sa.sa_handler;
+               spin_unlock_irq(&current->sighand->siglock);
+               if (handler == SIG_DFL) {
+                       /* init has generated a synchronous exception
+                          and it doesn't have a handler for the signal */
+                       printk(KERN_CRIT "init has generated signal %d "
+                              "but has no handler for it\n", signr);
+                       do_exit(signr);
+               }
+       }
 }
 
 /*
@@ -849,10 +871,12 @@ void AltivecAssistException(struct pt_regs *regs)
 }
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_E500
 void PerformanceMonitorException(struct pt_regs *regs)
 {
        perf_irq(regs);
 }
+#endif
 
 #ifdef CONFIG_FSL_BOOKE
 void CacheLockingException(struct pt_regs *regs, unsigned long address,
index 1c380e67d4357389e29429af3b6e4f3f77f8f935..f1e1fb4144f034a9be9197cffab83570efa9790d 100644 (file)
@@ -4,6 +4,5 @@
 
 obj-y                  := checksum.o string.o strcase.o dec_and_lock.o div64.o
 
-obj-$(CONFIG_SMP)      += locks.o
 obj-$(CONFIG_8xx)      += rheap.o
 obj-$(CONFIG_CPM2)     += rheap.o
index 4ee888070d914618ebdc8cc6abcd3dc7e8530351..b18f0d9a00fc70a8225260af62df6492b1f948c8 100644 (file)
  * has a cmpxchg, and where atomic->value is an int holding
  * the value of the atomic (i.e. the high bits aren't used
  * for a lock or anything like that).
- *
- * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
- * if spinlocks are empty and thus atomic_dec_and_lock is defined
- * to be atomic_dec_and_test - in that case we don't need it
- * defined here as well.
  */
-
-#ifndef ATOMIC_DEC_AND_LOCK
 int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 {
        int counter;
@@ -43,4 +36,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 }
 
 EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif /* ATOMIC_DEC_AND_LOCK */
index 57d9930843ac28f9d5c726071c8368fc8a69942b..ee5e9f25baf98d7c567361739ee30864bb8c980d 100644 (file)
@@ -278,11 +278,7 @@ bad_area:
 
        /* User mode accesses cause a SIGSEGV */
        if (user_mode(regs)) {
-               info.si_signo = SIGSEGV;
-               info.si_errno = 0;
-               info.si_code = code;
-               info.si_addr = (void __user *) address;
-               force_sig_info(SIGSEGV, &info, current);
+               _exception(SIGSEGV, regs, code, address);
                return 0;
        }
 
index ab83132a7ed0bf01cd571cfb40fb4aac0dbe2b7d..3ec87c91343e8f2dac625d7391117b165170571d 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
 #include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #ifdef CONFIG_SMP
        .comm   mmu_hash_lock,4
index 0fd3442f51310318ac15c1d954766854067b391e..d6b2b1965dcb30a179689705a1db8d627ac01abe 100644 (file)
@@ -91,15 +91,10 @@ ebony_calibrate_decr(void)
         * on Rev. C silicon then errata forces us to
         * use the internal clock.
         */
-       switch (PVR_REV(mfspr(SPRN_PVR))) {
-               case PVR_REV(PVR_440GP_RB):
-                       freq = EBONY_440GP_RB_SYSCLK;
-                       break;
-               case PVR_REV(PVR_440GP_RC1):
-               default:
-                       freq = EBONY_440GP_RC_SYSCLK;
-                       break;
-       }
+       if (strcmp(cur_cpu_spec[0]->cpu_name, "440GP Rev. B") == 0)
+               freq = EBONY_440GP_RB_SYSCLK;
+       else
+               freq = EBONY_440GP_RC_SYSCLK;
 
        ibm44x_calibrate_decr(freq);
 }
index b659d7b3d7477a8e9c520eac236b785a32637142..ff3796860123ae46ec899ea5da0a9afcaeeb7bdd 100644 (file)
@@ -58,7 +58,7 @@ static void parse_bootinfo(unsigned long r3,
 static void hdpu_set_l1pe(void);
 static void hdpu_cpustate_set(unsigned char new_state);
 #ifdef CONFIG_SMP
-static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(timebase_lock);
 static unsigned int timebase_upper = 0, timebase_lower = 0;
 extern int smp_tb_synchronized;
 
index 016a74649155b83b8547ba2b85656a7914e78674..88419c77ac439cd72b341c59dab10201efee9240 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/cputable.h>
 #include <asm/cache.h>
 #include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #define MAGIC  0x4c617273      /* 'Lars' */
 
@@ -161,6 +161,8 @@ _GLOBAL(low_sleep_handler)
        addi r3,r3,sleep_storage@l
        stw r5,0(r3)
 
+       .globl  low_cpu_die
+low_cpu_die:
        /* Flush & disable all caches */
        bl      flush_disable_caches
 
index 8e049dab4e6321f28354e0e821fe0569f36bac35..794a23994b82a09185b82ad3b797859ae96cda83 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/hardirq.h>
+#include <linux/cpu.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -55,9 +56,7 @@
  * Powersurge (old powermac SMP) support.
  */
 
-extern void __secondary_start_psurge(void);
-extern void __secondary_start_psurge2(void);   /* Temporary horrible hack */
-extern void __secondary_start_psurge3(void);   /* Temporary horrible hack */
+extern void __secondary_start_pmac_0(void);
 
 /* Addresses for powersurge registers */
 #define HAMMERHEAD_BASE                0xf8000000
@@ -119,7 +118,7 @@ static volatile int sec_tb_reset = 0;
 static unsigned int pri_tb_hi, pri_tb_lo;
 static unsigned int pri_tb_stamp;
 
-static void __init core99_init_caches(int cpu)
+static void __devinit core99_init_caches(int cpu)
 {
        if (!cpu_has_feature(CPU_FTR_L2CR))
                return;
@@ -346,7 +345,7 @@ static int __init smp_psurge_probe(void)
 
 static void __init smp_psurge_kick_cpu(int nr)
 {
-       void (*start)(void) = __secondary_start_psurge;
+       unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
        unsigned long a;
 
        /* may need to flush here if secondary bats aren't setup */
@@ -356,17 +355,7 @@ static void __init smp_psurge_kick_cpu(int nr)
 
        if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
 
-       /* setup entry point of secondary processor */
-       switch (nr) {
-       case 2:
-               start = __secondary_start_psurge2;
-               break;
-       case 3:
-               start = __secondary_start_psurge3;
-               break;
-       }
-
-       out_be32(psurge_start, __pa(start));
+       out_be32(psurge_start, start);
        mb();
 
        psurge_set_ipi(nr);
@@ -500,14 +489,14 @@ static int __init smp_core99_probe(void)
        return ncpus;
 }
 
-static void __init smp_core99_kick_cpu(int nr)
+static void __devinit smp_core99_kick_cpu(int nr)
 {
        unsigned long save_vector, new_vector;
        unsigned long flags;
 
        volatile unsigned long *vector
                 = ((volatile unsigned long *)(KERNELBASE+0x100));
-       if (nr < 1 || nr > 3)
+       if (nr < 0 || nr > 3)
                return;
        if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
 
@@ -518,19 +507,9 @@ static void __init smp_core99_kick_cpu(int nr)
        save_vector = *vector;
 
        /* Setup fake reset vector that does    
-        *   b __secondary_start_psurge - KERNELBASE
+        *   b __secondary_start_pmac_0 + nr*8 - KERNELBASE
         */
-       switch(nr) {
-               case 1:
-                       new_vector = (unsigned long)__secondary_start_psurge;
-                       break;
-               case 2:
-                       new_vector = (unsigned long)__secondary_start_psurge2;
-                       break;
-               case 3:
-                       new_vector = (unsigned long)__secondary_start_psurge3;
-                       break;
-       }
+       new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8;
        *vector = 0x48000002 + new_vector - KERNELBASE;
 
        /* flush data cache and inval instruction cache */
@@ -554,7 +533,7 @@ static void __init smp_core99_kick_cpu(int nr)
        if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
 }
 
-static void __init smp_core99_setup_cpu(int cpu_nr)
+static void __devinit smp_core99_setup_cpu(int cpu_nr)
 {
        /* Setup L2/L3 */
        if (cpu_nr != 0)
@@ -668,3 +647,47 @@ struct smp_ops_t core99_smp_ops __pmacdata = {
        .give_timebase  = smp_core99_give_timebase,
        .take_timebase  = smp_core99_take_timebase,
 };
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+int __cpu_disable(void)
+{
+       cpu_clear(smp_processor_id(), cpu_online_map);
+
+       /* XXX reset cpu affinity here */
+       openpic_set_priority(0xf);
+       asm volatile("mtdec %0" : : "r" (0x7fffffff));
+       mb();
+       udelay(20);
+       asm volatile("mtdec %0" : : "r" (0x7fffffff));
+       return 0;
+}
+
+extern void low_cpu_die(void) __attribute__((noreturn)); /* in pmac_sleep.S */
+static int cpu_dead[NR_CPUS];
+
+void cpu_die(void)
+{
+       local_irq_disable();
+       cpu_dead[smp_processor_id()] = 1;
+       mb();
+       low_cpu_die();
+}
+
+void __cpu_die(unsigned int cpu)
+{
+       int timeout;
+
+       timeout = 1000;
+       while (!cpu_dead[cpu]) {
+               if (--timeout == 0) {
+                       printk("CPU %u refused to die!\n", cpu);
+                       break;
+               }
+               msleep(1);
+       }
+       cpu_callin_map[cpu] = 0;
+       cpu_dead[cpu] = 0;
+}
+
+#endif
index 774709807538d593d6bc637040e112ce93fbbadc..75fe8eb1069359c3d52cbc3445d0ebd5b2658f26 100644 (file)
@@ -90,14 +90,10 @@ cpc700_mask_and_ack_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type cpc700_pic = {
-       "CPC700 PIC",
-       NULL,
-       NULL,
-       cpc700_unmask_irq,
-       cpc700_mask_irq,
-       cpc700_mask_and_ack_irq,
-       NULL,
-       NULL
+       .typename = "CPC700 PIC",
+       .enable = cpc700_unmask_irq,
+       .disable = cpc700_mask_irq,
+       .ack = cpc700_mask_and_ack_irq,
 };
 
 __init static void
index b9391e65014124f946d83704ef88e54cf58f3a8d..5c7908c20e43e8e2b3b023917e297296df1f99f1 100644 (file)
@@ -129,14 +129,11 @@ static void i8259_end_irq(unsigned int irq)
 }
 
 struct hw_interrupt_type i8259_pic = {
-       " i8259    ",
-       NULL,
-       NULL,
-       i8259_unmask_irq,
-       i8259_mask_irq,
-       i8259_mask_and_ack_irq,
-       i8259_end_irq,
-       NULL
+       .typename = " i8259    ",
+       .enable = i8259_unmask_irq,
+       .disable = i8259_mask_irq,
+       .ack = i8259_mask_and_ack_irq,
+       .end = i8259_end_irq,
 };
 
 static struct resource pic1_iores = {
index d4776af6a3ca210a49b519d98bd28ec72e071181..0bb919859b8be862b8cee9dcbba2994fd1caba53 100644 (file)
@@ -236,9 +236,10 @@ void __init ibm440gx_l2c_setup(struct ibm44x_clocks* p)
        /* Disable L2C on rev.A, rev.B and 800MHz version of rev.C,
           enable it on all other revisions
         */
-       u32 pvr = mfspr(SPRN_PVR);
-       if (pvr == PVR_440GX_RA || pvr == PVR_440GX_RB ||
-           (pvr == PVR_440GX_RC && p->cpu > 667000000))
+       if (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. A") == 0 ||
+                       strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. B") == 0
+                       || (strcmp(cur_cpu_spec[0]->cpu_name, "440GX Rev. C")
+                               == 0 && p->cpu > 667000000))
                ibm440gx_l2c_disable();
        else
                ibm440gx_l2c_enable();
index 6262b11f366f713eaf228ca10bb6e77ef206bb82..839f8872826f40480088397ddb9da28f716f1356 100644 (file)
@@ -31,7 +31,7 @@
 
 
 u8 mv64x60_pci_exclude_bridge = 1;
-spinlock_t     mv64x60_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(mv64x60_lock);
 
 static phys_addr_t     mv64x60_bridge_pbase;
 static void            *mv64x60_bridge_vbase;
index 7e272c51a4973e17e3deab27cb1f1754e086cfc7..2e0ea92144f6b3f15a759dc9f9983f0b49f711b7 100644 (file)
@@ -82,13 +82,11 @@ static void openpic2_end_irq(unsigned int irq_nr);
 static void openpic2_ack_irq(unsigned int irq_nr);
 
 struct hw_interrupt_type open_pic2 = {
-       " OpenPIC2 ",
-       NULL,
-       NULL,
-       openpic2_enable_irq,
-       openpic2_disable_irq,
-       openpic2_ack_irq,
-       openpic2_end_irq,
+       .typename = " OpenPIC2 ",
+       .enable = openpic2_enable_irq,
+       .disable = openpic2_disable_irq,
+       .ack = openpic2_ack_irq,
+       .end = openpic2_end_irq,
 };
 
 /*
index 06cb0af2a58d8d779791b6fdb8389d4e568dee8f..ce4d1deb86e930ee75c4228a44bd4e418a1d743f 100644 (file)
@@ -34,13 +34,10 @@ static void ppc403_aic_disable(unsigned int irq);
 static void ppc403_aic_disable_and_ack(unsigned int irq);
 
 static struct hw_interrupt_type ppc403_aic = {
-       "403GC AIC",
-       NULL,
-       NULL,
-       ppc403_aic_enable,
-       ppc403_aic_disable,
-       ppc403_aic_disable_and_ack,
-       0
+       .typename = "403GC AIC",
+       .enable = ppc403_aic_enable,
+       .disable = ppc403_aic_disable,
+       .ack = ppc403_aic_disable_and_ack,
 };
 
 int
index 57f4ed5e5ae1a1b6dbab371f5590409c0fa2b20d..0970b5d30391553877a031eab1f5e3ec8e790d9d 100644 (file)
@@ -94,7 +94,7 @@
 #define mk_config_type1(bus, dev, offset) \
        mk_config_addr(bus, dev, offset) | 1;
 
-static spinlock_t pcibios_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pcibios_lock);
 
 int qspan_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
                                  unsigned char offset, unsigned char *val)
index e0bd66f0847a5ff022bfdd2acd36de41ff60482c..2cbcad278cefc50cc273eeec464d29201e16f0f5 100644 (file)
@@ -79,14 +79,11 @@ xilinx_intc_end(unsigned int irq)
 }
 
 static struct hw_interrupt_type xilinx_intc = {
-       "Xilinx Interrupt Controller",
-       NULL,
-       NULL,
-       xilinx_intc_enable,
-       xilinx_intc_disable,
-       xilinx_intc_disable_and_ack,
-       xilinx_intc_end,
-       0
+       .typename = "Xilinx Interrupt Controller",
+       .enable = xilinx_intc_enable,
+       .disable = xilinx_intc_disable,
+       .ack = xilinx_intc_disable_and_ack,
+       .end = xilinx_intc_end,
 };
 
 int
index a91daa324e888464c825a42f6ecb252df291025b..17d2c1eac3b8567e8cd711f3dd72a0c1bf037a82 100644 (file)
@@ -56,7 +56,7 @@ LDFLAGS_vmlinux       := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
 CFLAGS         += -msoft-float -pipe -mminimal-toc -mtraceback=none \
                   -mcall-aixdesc
 # Temporary hack until we have migrated to asm-powerpc
-CPPFLAGS       += -Iinclude3
+CPPFLAGS       += -Iarch/$(ARCH)/include
 
 GCC_VERSION     := $(call cc-version)
 GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;)
@@ -115,21 +115,15 @@ all: $(KBUILD_IMAGE)
 
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
-       $(Q)rm -rf include3
+       # Temporary hack until we have migrated to asm-powerpc
+       $(Q)rm -rf arch/$(ARCH)/include
 
-prepare: include/asm-ppc64/offsets.h
-
-arch/ppc64/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
 
 # Temporary hack until we have migrated to asm-powerpc
-include/asm: include3/asm
-include3/asm:
-       $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi;
-       $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm
+include/asm: arch/$(ARCH)/include/asm
+arch/$(ARCH)/include/asm:
+       $(Q)if [ ! -d arch/$(ARCH)/include ]; then mkdir -p arch/$(ARCH)/include; fi
+       $(Q)ln -fsn $(srctree)/include/asm-powerpc arch/$(ARCH)/include/asm
 
 define archhelp
   echo  '  zImage.vmode        - Compressed kernel image (arch/$(ARCH)/boot/zImage.vmode)'
@@ -139,5 +133,3 @@ define archhelp
   echo  '  zImage              - zImage for pSeries machines'
   echo  '  zImage.initrd       - zImage with initrd for pSeries machines'
 endef
-
-CLEAN_FILES += include/asm-ppc64/offsets.h
index 0482c063c26ee2162ec85f69e2dbb8797fee6087..1fb673c511ff504972e0568fbfaf35d88ab290a6 100644 (file)
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <asm/ppc_asm.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
 _GLOBAL(__970_cpu_preinit)
index bf99b4a92f20864313c7d79211a5d5a6db68a7ce..d133a49cdf8972270fcd1f668f1d43cbea1a6766 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/mmu.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cputable.h>
 
 #ifdef CONFIG_PPC_ISERIES
index b436206e317df175118e3aed5ac28441e06980d7..58c314738c9987f441ef29a273c551436db1650e 100644 (file)
@@ -30,7 +30,7 @@
 #include <asm/mmu.h>
 #include <asm/systemcfg.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/bug.h>
 #include <asm/cputable.h>
 #include <asm/setup.h>
index 356e4fd9a94fecc763e90a13bb79860ba2880f7b..fbc273c32bcc176556a5949b0fc2c7b78a331bfb 100644 (file)
@@ -252,7 +252,7 @@ unsigned long __init find_and_init_phbs(void)
                        phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
                        if (phb == NULL)
                                return -ENOMEM;
-                               pci_setup_pci_controller(phb);
+                       pci_setup_pci_controller(phb);
 
                        phb->pci_mem_offset = phb->local_number = bus;
                        phb->first_busno = bus;
index 97e4a26550402dbd6dc9199a9adac7b8541f6ab7..ca02afe2a7953ad5d21f8a8567d5988dd5271b7e 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 #undef DEBUG
 
index 5a8b4d8c2dd62042e8b67a237fa51d89b8797884..1d297e0edfc0d272e9676562a08866ee6acbf31d 100644 (file)
@@ -283,7 +283,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
         * the reg address cell, we shall fix that by killing struct
         * reg_property and using some accessor functions instead
         */
-               hose->first_busno = 0xf0;
+       hose->first_busno = 0xf0;
        hose->last_busno = 0xff;
        hose->ops = &u3_agp_pci_ops;
        hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
@@ -315,24 +315,24 @@ static int __init add_bridge(struct device_node *dev)
        char* disp_name;
        int *bus_range;
        int primary = 1;
-       struct property *of_prop;
+       struct property *of_prop;
 
        DBG("Adding PCI host bridge %s\n", dev->full_name);
 
-               bus_range = (int *) get_property(dev, "bus-range", &len);
-               if (bus_range == NULL || len < 2 * sizeof(int)) {
-                       printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
-                                      dev->full_name);
-               }
+       bus_range = (int *) get_property(dev, "bus-range", &len);
+       if (bus_range == NULL || len < 2 * sizeof(int)) {
+               printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+               dev->full_name);
+       }
 
        hose = alloc_bootmem(sizeof(struct pci_controller));
        if (hose == NULL)
                return -ENOMEM;
-               pci_setup_pci_controller(hose);
+       pci_setup_pci_controller(hose);
 
-               hose->arch_data = dev;
-               hose->first_busno = bus_range ? bus_range[0] : 0;
-               hose->last_busno = bus_range ? bus_range[1] : 0xff;
+       hose->arch_data = dev;
+       hose->first_busno = bus_range ? bus_range[0] : 0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        of_prop = alloc_bootmem(sizeof(struct property) +
                                sizeof(hose->global_number));
@@ -346,25 +346,25 @@ static int __init add_bridge(struct device_node *dev)
        }
 
        disp_name = NULL;
-               if (device_is_compatible(dev, "u3-agp")) {
-                       setup_u3_agp(hose);
-                       disp_name = "U3-AGP";
-                       primary = 0;
-               } else if (device_is_compatible(dev, "u3-ht")) {
-                       setup_u3_ht(hose);
-                       disp_name = "U3-HT";
-                       primary = 1;
-               }
-               printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
-                       disp_name, hose->first_busno, hose->last_busno);
-
-               /* Interpret the "ranges" property */
-               /* This also maps the I/O region and sets isa_io/mem_base */
-               pci_process_bridge_OF_ranges(hose, dev);
+       if (device_is_compatible(dev, "u3-agp")) {
+               setup_u3_agp(hose);
+               disp_name = "U3-AGP";
+               primary = 0;
+       } else if (device_is_compatible(dev, "u3-ht")) {
+               setup_u3_ht(hose);
+               disp_name = "U3-HT";
+               primary = 1;
+       }
+       printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+               disp_name, hose->first_busno, hose->last_busno);
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pci_process_bridge_OF_ranges(hose, dev);
        pci_setup_phb_io(hose, primary);
 
-               /* Fixup "bus-range" OF property */
-               fixup_bus_range(dev);
+       /* Fixup "bus-range" OF property */
+       fixup_bus_range(dev);
 
        return 0;
 }
index c047663eb48d14c9bf6e09f5f15b32a3f00bdf8c..e7241ad80a08212758c2e2c2538246595714c21c 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/page.h>
 #include <asm/cache.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cputable.h>
 
        .text
index 9490b6c5b1736ae7fa5b42b7cbdf9a02020bd791..bfadccc7b8be78e4683fcb0bac7f1fd5189ab3ab 100644 (file)
@@ -590,6 +590,13 @@ static int pseries_shared_idle(void)
        return 0;
 }
 
+static int pSeries_pci_probe_mode(struct pci_bus *bus)
+{
+       if (systemcfg->platform & PLATFORM_LPAR)
+               return PCI_PROBE_DEVTREE;
+       return PCI_PROBE_NORMAL;
+}
+
 struct machdep_calls __initdata pSeries_md = {
        .probe                  = pSeries_probe,
        .setup_arch             = pSeries_setup_arch,
@@ -597,6 +604,7 @@ struct machdep_calls __initdata pSeries_md = {
        .get_cpuinfo            = pSeries_get_cpuinfo,
        .log_error              = pSeries_log_error,
        .pcibios_fixup          = pSeries_final_fixup,
+       .pci_probe_mode         = pSeries_pci_probe_mode,
        .irq_bus_setup          = pSeries_irq_bus_setup,
        .restart                = rtas_restart,
        .power_off              = rtas_power_off,
index 79c7f32236658805bab9f783d80cb3d42091893a..d2c7e2c4733b72130cbd90020b0ae61cc7ed4897 100644 (file)
@@ -272,6 +272,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
        unsigned long start_here = __pa((u32)*((unsigned long *)
                                               pSeries_secondary_smp_init));
        unsigned int pcpu;
+       int start_cpu;
 
        if (cpu_isset(lcpu, of_spin_map))
                /* Already started by OF and sitting in spin loop */
@@ -282,12 +283,20 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
        /* Fixup atomic count: it exited inside IRQ handler. */
        paca[lcpu].__current->thread_info->preempt_count        = 0;
 
-       status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
-                          pcpu, start_here, lcpu);
+       /* 
+        * If the RTAS start-cpu token does not exist then presume the
+        * cpu is already spinning.
+        */
+       start_cpu = rtas_token("start-cpu");
+       if (start_cpu == RTAS_UNKNOWN_SERVICE)
+               return 1;
+
+       status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, lcpu);
        if (status != 0) {
                printk(KERN_ERR "start-cpu failed: %i\n", status);
                return 0;
        }
+
        return 1;
 }
 
index 8447dcc2c2b3f7db34086a997030c7d92742dd0a..861138ad092c597efcaee48d9d6496e9f41a7057 100644 (file)
@@ -51,6 +51,10 @@ unsigned long io_page_mask;
 
 EXPORT_SYMBOL(io_page_mask);
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static void fixup_resource(struct resource *res, struct pci_dev *dev);
+static void do_bus_setup(struct pci_bus *bus);
+#endif
 
 unsigned int pcibios_assign_all_busses(void)
 {
@@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void)
 }
 #endif
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
+{
+       u32 *prop;
+       int len;
+
+       prop = (u32 *) get_property(np, name, &len);
+       if (prop && len >= 4)
+               return *prop;
+       return def;
+}
+
+static unsigned int pci_parse_of_flags(u32 addr0)
+{
+       unsigned int flags = 0;
+
+       if (addr0 & 0x02000000) {
+               flags |= IORESOURCE_MEM;
+               if (addr0 & 0x40000000)
+                       flags |= IORESOURCE_PREFETCH;
+       } else if (addr0 & 0x01000000)
+               flags |= IORESOURCE_IO;
+       return flags;
+}
+
+#define GET_64BIT(prop, i)     ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
+
+static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
+{
+       u64 base, size;
+       unsigned int flags;
+       struct resource *res;
+       u32 *addrs, i;
+       int proplen;
+
+       addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
+       if (!addrs)
+               return;
+       for (; proplen >= 20; proplen -= 20, addrs += 5) {
+               flags = pci_parse_of_flags(addrs[0]);
+               if (!flags)
+                       continue;
+               base = GET_64BIT(addrs, 1);
+               size = GET_64BIT(addrs, 3);
+               if (!size)
+                       continue;
+               i = addrs[0] & 0xff;
+               if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
+                       res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
+               } else if (i == dev->rom_base_reg) {
+                       res = &dev->resource[PCI_ROM_RESOURCE];
+                       flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
+               } else {
+                       printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i);
+                       continue;
+               }
+               res->start = base;
+               res->end = base + size - 1;
+               res->flags = flags;
+               res->name = pci_name(dev);
+               fixup_resource(res, dev);
+       }
+}
+
+static struct pci_dev *of_create_pci_dev(struct device_node *node,
+                                        struct pci_bus *bus, int devfn)
+{
+       struct pci_dev *dev;
+       const char *type;
+
+       dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+       type = get_property(node, "device_type", NULL);
+       if (type == NULL)
+               type = "";
+
+       memset(dev, 0, sizeof(struct pci_dev));
+       dev->bus = bus;
+       dev->sysdata = node;
+       dev->dev.parent = bus->bridge;
+       dev->dev.bus = &pci_bus_type;
+       dev->devfn = devfn;
+       dev->multifunction = 0;         /* maybe a lie? */
+
+       dev->vendor = get_int_prop(node, "vendor-id", 0xffff);
+       dev->device = get_int_prop(node, "device-id", 0xffff);
+       dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
+       dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
+
+       dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+
+       sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
+               dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
+       dev->class = get_int_prop(node, "class-code", 0);
+
+       dev->current_state = 4;         /* unknown power state */
+
+       if (!strcmp(type, "pci")) {
+               /* a PCI-PCI bridge */
+               dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
+               dev->rom_base_reg = PCI_ROM_ADDRESS1;
+       } else if (!strcmp(type, "cardbus")) {
+               dev->hdr_type = PCI_HEADER_TYPE_CARDBUS;
+       } else {
+               dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
+               dev->rom_base_reg = PCI_ROM_ADDRESS;
+               dev->irq = NO_IRQ;
+               if (node->n_intrs > 0) {
+                       dev->irq = node->intrs[0].line;
+                       pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+                                             dev->irq);
+               }
+       }
+
+       pci_parse_of_addrs(node, dev);
+
+       pci_device_add(dev, bus);
+
+       /* XXX pci_scan_msi_device(dev); */
+
+       return dev;
+}
+
+static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev);
+
+static void __devinit of_scan_bus(struct device_node *node,
+                                 struct pci_bus *bus)
+{
+       struct device_node *child = NULL;
+       u32 *reg;
+       int reglen, devfn;
+       struct pci_dev *dev;
+
+       while ((child = of_get_next_child(node, child)) != NULL) {
+               reg = (u32 *) get_property(child, "reg", &reglen);
+               if (reg == NULL || reglen < 20)
+                       continue;
+               devfn = (reg[0] >> 8) & 0xff;
+               /* create a new pci_dev for this device */
+               dev = of_create_pci_dev(child, bus, devfn);
+               if (!dev)
+                       continue;
+               if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+                   dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+                       of_scan_pci_bridge(child, dev);
+       }
+
+       do_bus_setup(bus);
+}
+
+static void __devinit of_scan_pci_bridge(struct device_node *node,
+                                        struct pci_dev *dev)
+{
+       struct pci_bus *bus;
+       u32 *busrange, *ranges;
+       int len, i, mode;
+       struct resource *res;
+       unsigned int flags;
+       u64 size;
+
+       /* parse bus-range property */
+       busrange = (u32 *) get_property(node, "bus-range", &len);
+       if (busrange == NULL || len != 8) {
+               printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n",
+                      node->full_name);
+               return;
+       }
+       ranges = (u32 *) get_property(node, "ranges", &len);
+       if (ranges == NULL) {
+               printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n",
+                      node->full_name);
+               return;
+       }
+
+       bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
+       if (!bus) {
+               printk(KERN_ERR "Failed to create pci bus for %s\n",
+                      node->full_name);
+               return;
+       }
+
+       bus->primary = dev->bus->number;
+       bus->subordinate = busrange[1];
+       bus->bridge_ctl = 0;
+       bus->sysdata = node;
+
+       /* parse ranges property */
+       /* PCI #address-cells == 3 and #size-cells == 2 always */
+       res = &dev->resource[PCI_BRIDGE_RESOURCES];
+       for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) {
+               res->flags = 0;
+               bus->resource[i] = res;
+               ++res;
+       }
+       i = 1;
+       for (; len >= 32; len -= 32, ranges += 8) {
+               flags = pci_parse_of_flags(ranges[0]);
+               size = GET_64BIT(ranges, 6);
+               if (flags == 0 || size == 0)
+                       continue;
+               if (flags & IORESOURCE_IO) {
+                       res = bus->resource[0];
+                       if (res->flags) {
+                               printk(KERN_ERR "PCI: ignoring extra I/O range"
+                                      " for bridge %s\n", node->full_name);
+                               continue;
+                       }
+               } else {
+                       if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) {
+                               printk(KERN_ERR "PCI: too many memory ranges"
+                                      " for bridge %s\n", node->full_name);
+                               continue;
+                       }
+                       res = bus->resource[i];
+                       ++i;
+               }
+               res->start = GET_64BIT(ranges, 1);
+               res->end = res->start + size - 1;
+               res->flags = flags;
+               fixup_resource(res, dev);
+       }
+       sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
+               bus->number);
+
+       mode = PCI_PROBE_NORMAL;
+       if (ppc_md.pci_probe_mode)
+               mode = ppc_md.pci_probe_mode(bus);
+       if (mode == PCI_PROBE_DEVTREE)
+               of_scan_bus(node, bus);
+       else if (mode == PCI_PROBE_NORMAL)
+               pci_scan_child_bus(bus);
+}
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+static void __devinit scan_phb(struct pci_controller *hose)
+{
+       struct pci_bus *bus;
+       struct device_node *node = hose->arch_data;
+       int i, mode;
+       struct resource *res;
+
+       bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
+       if (bus == NULL) {
+               printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+                      hose->global_number);
+               return;
+       }
+       bus->secondary = hose->first_busno;
+       hose->bus = bus;
+
+       bus->resource[0] = res = &hose->io_resource;
+       if (res->flags && request_resource(&ioport_resource, res))
+               printk(KERN_ERR "Failed to request PCI IO region "
+                      "on PCI domain %04x\n", hose->global_number);
+
+       for (i = 0; i < 3; ++i) {
+               res = &hose->mem_resources[i];
+               bus->resource[i+1] = res;
+               if (res->flags && request_resource(&iomem_resource, res))
+                       printk(KERN_ERR "Failed to request PCI memory region "
+                              "on PCI domain %04x\n", hose->global_number);
+       }
+
+       mode = PCI_PROBE_NORMAL;
+#ifdef CONFIG_PPC_MULTIPLATFORM
+       if (ppc_md.pci_probe_mode)
+               mode = ppc_md.pci_probe_mode(bus);
+       if (mode == PCI_PROBE_DEVTREE) {
+               bus->subordinate = hose->last_busno;
+               of_scan_bus(node, bus);
+       }
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+       if (mode == PCI_PROBE_NORMAL)
+               hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+       pci_bus_add_devices(bus);
+}
+
 static int __init pcibios_init(void)
 {
        struct pci_controller *hose, *tmp;
-       struct pci_bus *bus;
 
        /* For now, override phys_mem_access_prot. If we need it,
         * later, we may move that initialization to each ppc_md
@@ -242,13 +523,8 @@ static int __init pcibios_init(void)
        printk("PCI: Probing PCI hardware\n");
 
        /* Scan all of the recorded PCI controllers.  */
-       list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-               hose->last_busno = 0xff;
-               bus = pci_scan_bus(hose->first_busno, hose->ops,
-                                  hose->arch_data);
-               hose->bus = bus;
-               hose->last_busno = bus->subordinate;
-       }
+       list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+               scan_phb(hose);
 
 #ifndef CONFIG_PPC_ISERIES
        if (pci_probe_only)
@@ -820,120 +1096,89 @@ void phbs_remap_io(void)
 /*
  * ppc64 can have multifunction devices that do not respond to function 0.
  * In this case we must scan all functions.
+ * XXX this can go now, we use the OF device tree in all the
+ * cases that caused problems. -- paulus
  */
 int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
 {
-       struct device_node *busdn, *dn;
-
-       if (bus->self)
-               busdn = pci_device_to_OF_node(bus->self);
-       else
-               busdn = bus->sysdata;   /* must be a phb */
-
-       if (busdn == NULL)
-              return 0;
-
-       /*
-        * Check to see if there is any of the 8 functions are in the
-        * device tree.  If they are then we need to scan all the
-        * functions of this slot.
-        */
-       for (dn = busdn->child; dn; dn = dn->sibling) {
-              struct pci_dn *pdn = dn->data;
-              if (pdn && (pdn->devfn >> 3) == (devfn >> 3))
-                       return 1;
-       }
-
        return 0;
 }
 
+static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
+{
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       unsigned long start, end, mask, offset;
+
+       if (res->flags & IORESOURCE_IO) {
+               offset = (unsigned long)hose->io_base_virt - pci_io_base;
+
+               start = res->start += offset;
+               end = res->end += offset;
+
+               /* Need to allow IO access to pages that are in the
+                  ISA range */
+               if (start < MAX_ISA_PORT) {
+                       if (end > MAX_ISA_PORT)
+                               end = MAX_ISA_PORT;
+
+                       start >>= PAGE_SHIFT;
+                       end >>= PAGE_SHIFT;
+
+                       /* get the range of pages for the map */
+                       mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
+                       io_page_mask |= mask;
+               }
+       } else if (res->flags & IORESOURCE_MEM) {
+               res->start += hose->pci_mem_offset;
+               res->end += hose->pci_mem_offset;
+       }
+}
 
 void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-                                          struct pci_bus *bus)
+                                             struct pci_bus *bus)
 {
        /* Update device resources.  */
-       struct pci_controller *hose = pci_bus_to_host(bus);
        int i;
 
-       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-               if (dev->resource[i].flags & IORESOURCE_IO) {
-                       unsigned long offset = (unsigned long)hose->io_base_virt
-                               - pci_io_base;
-                        unsigned long start, end, mask;
-
-                        start = dev->resource[i].start += offset;
-                        end = dev->resource[i].end += offset;
-
-                        /* Need to allow IO access to pages that are in the
-                           ISA range */
-                        if (start < MAX_ISA_PORT) {
-                                if (end > MAX_ISA_PORT)
-                                        end = MAX_ISA_PORT;
-
-                                start >>= PAGE_SHIFT;
-                                end >>= PAGE_SHIFT;
-
-                                /* get the range of pages for the map */
-                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
-                                io_page_mask |= mask;
-                        }
-               }
-                else if (dev->resource[i].flags & IORESOURCE_MEM) {
-                       dev->resource[i].start += hose->pci_mem_offset;
-                       dev->resource[i].end += hose->pci_mem_offset;
-               }
-        }
+       for (i = 0; i < PCI_NUM_RESOURCES; i++)
+               if (dev->resource[i].flags)
+                       fixup_resource(&dev->resource[i], dev);
 }
 EXPORT_SYMBOL(pcibios_fixup_device_resources);
 
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+static void __devinit do_bus_setup(struct pci_bus *bus)
 {
-       struct pci_controller *hose = pci_bus_to_host(bus);
-       struct pci_dev *dev = bus->self;
-       struct resource *res;
-       int i;
+       struct pci_dev *dev;
 
-       if (!dev) {
-               /* Root bus. */
+       ppc_md.iommu_bus_setup(bus);
 
-               hose->bus = bus;
-               bus->resource[0] = res = &hose->io_resource;
+       list_for_each_entry(dev, &bus->devices, bus_list)
+               ppc_md.iommu_dev_setup(dev);
 
-               if (res->flags && request_resource(&ioport_resource, res))
-                       printk(KERN_ERR "Failed to request IO on "
-                                       "PCI domain %d\n", pci_domain_nr(bus));
+       if (ppc_md.irq_bus_setup)
+               ppc_md.irq_bus_setup(bus);
+}
 
-               for (i = 0; i < 3; ++i) {
-                       res = &hose->mem_resources[i];
-                       bus->resource[i+1] = res;
-                       if (res->flags && request_resource(&iomem_resource, res))
-                               printk(KERN_ERR "Failed to request MEM on "
-                                               "PCI domain %d\n",
-                                               pci_domain_nr(bus));
-               }
-       } else if (pci_probe_only &&
-                  (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+       struct pci_dev *dev = bus->self;
+
+       if (dev && pci_probe_only &&
+           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
                /* This is a subordinate bridge */
 
                pci_read_bridge_bases(bus);
                pcibios_fixup_device_resources(dev, bus);
        }
 
-       ppc_md.iommu_bus_setup(bus);
-
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               ppc_md.iommu_dev_setup(dev);
-
-       if (ppc_md.irq_bus_setup)
-               ppc_md.irq_bus_setup(bus);
+       do_bus_setup(bus);
 
        if (!pci_probe_only)
                return;
 
-       list_for_each_entry(dev, &bus->devices, bus_list) {
+       list_for_each_entry(dev, &bus->devices, bus_list)
                if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
                        pcibios_fixup_device_resources(dev, bus);
-       }
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
index d37bff2d7d40c3ae9af84e8b9d047fa53766bdb2..dc40a0cad0b47e387e2b207e43f0d70eebdf80ac 100644 (file)
@@ -388,7 +388,7 @@ static void __init setup_u3_agp(struct pci_controller* hose)
         * the reg address cell, we shall fix that by killing struct
         * reg_property and using some accessor functions instead
         */
-               hose->first_busno = 0xf0;
+       hose->first_busno = 0xf0;
        hose->last_busno = 0xff;
        has_uninorth = 1;
        hose->ops = &macrisc_pci_ops;
@@ -473,7 +473,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
                        continue;
                }               
                cur++;
-                       DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
+               DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n",
                    cur-1, res->start - 1, cur, res->end + 1);
                hose->mem_resources[cur].name = np->full_name;
                hose->mem_resources[cur].flags = IORESOURCE_MEM;
@@ -603,24 +603,24 @@ static int __init add_bridge(struct device_node *dev)
        char* disp_name;
        int *bus_range;
        int primary = 1;
-       struct property *of_prop;
+       struct property *of_prop;
 
        DBG("Adding PCI host bridge %s\n", dev->full_name);
 
-               bus_range = (int *) get_property(dev, "bus-range", &len);
-               if (bus_range == NULL || len < 2 * sizeof(int)) {
-                       printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
-                                      dev->full_name);
-               }
+       bus_range = (int *) get_property(dev, "bus-range", &len);
+       if (bus_range == NULL || len < 2 * sizeof(int)) {
+               printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+                       dev->full_name);
+       }
 
        hose = alloc_bootmem(sizeof(struct pci_controller));
        if (hose == NULL)
                return -ENOMEM;
-               pci_setup_pci_controller(hose);
+       pci_setup_pci_controller(hose);
 
-               hose->arch_data = dev;
-               hose->first_busno = bus_range ? bus_range[0] : 0;
-               hose->last_busno = bus_range ? bus_range[1] : 0xff;
+       hose->arch_data = dev;
+       hose->first_busno = bus_range ? bus_range[0] : 0;
+       hose->last_busno = bus_range ? bus_range[1] : 0xff;
 
        of_prop = alloc_bootmem(sizeof(struct property) +
                                sizeof(hose->global_number));
@@ -634,24 +634,24 @@ static int __init add_bridge(struct device_node *dev)
        }
 
        disp_name = NULL;
-               if (device_is_compatible(dev, "u3-agp")) {
-                       setup_u3_agp(hose);
-                       disp_name = "U3-AGP";
-                       primary = 0;
-               } else if (device_is_compatible(dev, "u3-ht")) {
-                       setup_u3_ht(hose);
-                       disp_name = "U3-HT";
-                       primary = 1;
-               }
-               printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
-                       disp_name, hose->first_busno, hose->last_busno);
-
-               /* Interpret the "ranges" property */
-               /* This also maps the I/O region and sets isa_io/mem_base */
-               pmac_process_bridge_OF_ranges(hose, dev, primary);
-
-               /* Fixup "bus-range" OF property */
-               fixup_bus_range(dev);
+       if (device_is_compatible(dev, "u3-agp")) {
+               setup_u3_agp(hose);
+               disp_name = "U3-AGP";
+               primary = 0;
+       } else if (device_is_compatible(dev, "u3-ht")) {
+               setup_u3_ht(hose);
+               disp_name = "U3-HT";
+               primary = 1;
+       }
+       printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+               disp_name, hose->first_busno, hose->last_busno);
+
+       /* Interpret the "ranges" property */
+       /* This also maps the I/O region and sets isa_io/mem_base */
+       pmac_process_bridge_OF_ranges(hose, dev, primary);
+
+       /* Fixup "bus-range" OF property */
+       fixup_bus_range(dev);
 
        return 0;
 }
index e7f695dcd8c8dd4dae28d7626e421f93397eca19..325426c7bed00f5348ac0fc2dcdb64949a3ff716 100644 (file)
@@ -477,6 +477,18 @@ static int __init pmac_probe(int platform)
        return 1;
 }
 
+static int pmac_probe_mode(struct pci_bus *bus)
+{
+       struct device_node *node = bus->sysdata;
+
+       /* We need to use normal PCI probing for the AGP bus,
+          since the device for the AGP bridge isn't in the tree. */
+       if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+               return PCI_PROBE_NORMAL;
+
+       return PCI_PROBE_DEVTREE;
+}
+
 struct machdep_calls __initdata pmac_md = {
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_die                = generic_mach_cpu_die,
@@ -488,6 +500,7 @@ struct machdep_calls __initdata pmac_md = {
        .init_IRQ               = pmac_init_IRQ,
        .get_irq                = mpic_get_irq,
        .pcibios_fixup          = pmac_pcibios_fixup,
+       .pci_probe_mode         = pmac_probe_mode,
        .restart                = pmac_restart,
        .power_off              = pmac_power_off,
        .halt                   = pmac_halt,
index cdfec7438d0132334f17b65ec539fa919c997b91..63d9481c3ec2f7548cda86435c5b6a1311292b0f 100644 (file)
@@ -26,7 +26,7 @@ static void dummy_perf(struct pt_regs *regs)
        mtspr(SPRN_MMCR0, mmcr0);
 }
 
-static spinlock_t pmc_owner_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pmc_owner_lock);
 static void *pmc_owner_caller; /* mostly for debugging */
 perf_irq_t perf_irq = dummy_perf;
 
index 7a7e027653ad922dac160da11e545401696148ed..887005358eb1faa40bdba25f77d75650f21d851a 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/time.h>
+#include <asm/plpar_wrappers.h>
 
 #ifndef CONFIG_SMP
 struct task_struct *last_task_used_math = NULL;
@@ -163,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
 
 #endif /* CONFIG_ALTIVEC */
 
+static void set_dabr_spr(unsigned long val)
+{
+       mtspr(SPRN_DABR, val);
+}
+
+int set_dabr(unsigned long dabr)
+{
+       int ret = 0;
+
+       if (firmware_has_feature(FW_FEATURE_XDABR)) {
+               /* We want to catch accesses from kernel and userspace */
+               unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER;
+               ret = plpar_set_xdabr(dabr, flags);
+       } else if (firmware_has_feature(FW_FEATURE_DABR)) {
+               ret = plpar_set_dabr(dabr);
+       } else {
+               set_dabr_spr(dabr);
+       }
+
+       return ret;
+}
+
 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+static DEFINE_PER_CPU(unsigned long, current_dabr);
 
 struct task_struct *__switch_to(struct task_struct *prev,
                                struct task_struct *new)
@@ -198,6 +222,11 @@ struct task_struct *__switch_to(struct task_struct *prev,
                new->thread.regs->msr |= MSR_VEC;
 #endif /* CONFIG_ALTIVEC */
 
+       if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) {
+               set_dabr(new->thread.dabr);
+               __get_cpu_var(current_dabr) = new->thread.dabr;
+       }
+
        flush_tlb_pending();
 
        new_thread = &new->thread;
@@ -334,6 +363,11 @@ void flush_thread(void)
                last_task_used_altivec = NULL;
 #endif /* CONFIG_ALTIVEC */
 #endif /* CONFIG_SMP */
+
+       if (current->thread.dabr) {
+               current->thread.dabr = 0;
+               set_dabr(0);
+       }
 }
 
 void
index 2993f108d96d309f6f333bb47b38c86373551239..85ed3188a91d0a7ef7c3799c8cf9a7992f411ac1 100644 (file)
@@ -17,6 +17,7 @@
  * this archive for more details.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -206,6 +207,19 @@ int sys_ptrace(long request, long pid, long addr, long data)
                break;
        }
 
+       case PTRACE_GET_DEBUGREG: {
+               ret = -EINVAL;
+               /* We only support one DABR and no IABRS at the moment */
+               if (addr > 0)
+                       break;
+               ret = put_user(child->thread.dabr,
+                              (unsigned long __user *)data);
+               break;
+       }
+
+       case PTRACE_SET_DEBUGREG:
+               ret = ptrace_set_debugreg(child, addr, data);
+
        case PTRACE_DETACH:
                ret = ptrace_detach(child, data);
                break;
@@ -274,6 +288,20 @@ int sys_ptrace(long request, long pid, long addr, long data)
                break;
        }
 
+#ifdef CONFIG_ALTIVEC
+       case PTRACE_GETVRREGS:
+               /* Get the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = get_vrregs((unsigned long __user *)data, child);
+               break;
+
+       case PTRACE_SETVRREGS:
+               /* Set the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = set_vrregs(child, (unsigned long __user *)data);
+               break;
+#endif
+
        default:
                ret = ptrace_request(child, request, addr, data);
                break;
index 16436426c7e240db5e6599436d149e32d3412aa6..fb8c22d6084a7c280a0c74d9f9d3f1ebb523471d 100644 (file)
@@ -17,6 +17,7 @@
  * this archive for more details.
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -337,6 +338,19 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
                break;
        }
 
+       case PTRACE_GET_DEBUGREG: {
+               ret = -EINVAL;
+               /* We only support one DABR and no IABRS at the moment */
+               if (addr > 0)
+                       break;
+               ret = put_user(child->thread.dabr, (u32 __user *)data);
+               break;
+       }
+
+       case PTRACE_SET_DEBUGREG:
+               ret = ptrace_set_debugreg(child, addr, data);
+               break;
+
        case PTRACE_DETACH:
                ret = ptrace_detach(child, data);
                break;
@@ -405,9 +419,23 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
                break;
        }
 
-       case PTRACE_GETEVENTMSG:
-                ret = put_user(child->ptrace_message, (unsigned int __user *) data);
-                break;
+       case PTRACE_GETEVENTMSG:
+               ret = put_user(child->ptrace_message, (unsigned int __user *) data);
+               break;
+
+#ifdef CONFIG_ALTIVEC
+       case PTRACE_GETVRREGS:
+               /* Get the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = get_vrregs((unsigned long __user *)data, child);
+               break;
+
+       case PTRACE_SETVRREGS:
+               /* Set the child altivec register state. */
+               flush_altivec_to_thread(child);
+               ret = set_vrregs(child, (unsigned long __user *)data);
+               break;
+#endif
 
        default:
                ret = ptrace_request(child, request, addr, data);
index 3c00f7bfc1b5736d43ab2011e3ac37aafe6da9cf..41b97dc9cc0a0a9735675bdee038bf7b7008007e 100644 (file)
@@ -59,8 +59,6 @@ char mce_data_buf[RTAS_ERROR_LOG_MAX]
 /* This is true if we are using the firmware NMI handler (typically LPAR) */
 extern int fwnmi_active;
 
-extern void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
-
 static int ras_get_sensor_state_token;
 static int ras_check_exception_token;
 
index bfa8791c9807f865bb89085f0054759bbd452eaa..5ac48bd64891f98e0846ef8f0959ccba01da682b 100644 (file)
@@ -1064,8 +1064,6 @@ void __init setup_arch(char **cmdline_p)
 #define PPC64_LINUX_FUNCTION 0x0f000000
 #define PPC64_IPL_MESSAGE 0xc0000000
 #define PPC64_TERM_MESSAGE 0xb0000000
-#define PPC64_ATTN_MESSAGE 0xa0000000
-#define PPC64_DUMP_MESSAGE 0xd0000000
 
 static void ppc64_do_msg(unsigned int src, const char *msg)
 {
@@ -1093,20 +1091,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
        printk("[terminate]%04x %s\n", src, msg);
 }
 
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg)
-{
-       ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);
-       printk("[attention]%04x %s\n", src, msg);
-}
-
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg)
-{
-       ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);
-       printk("[dump]%04x %s\n", src, msg);
-}
-
 /* This should only be called on processor 0 during calibrate decr */
 void __init setup_default_decr(void)
 {
index 49a79a55c32de7d5ab73191dbe78047a6dcf848e..347112cca3c096ac660a3eed66d7aa4b9c0e0b26 100644 (file)
@@ -550,6 +550,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
                /* Whee!  Actually deliver the signal.  */
                if (TRAP(regs) == 0x0C00)
                        syscall_restart(regs, &ka);
+
+               /*
+                * Reenable the DABR before delivering the signal to
+                * user space. The DABR will have been cleared if it
+                * triggered inside the kernel.
+                */
+               if (current->thread.dabr)
+                       set_dabr(current->thread.dabr);
+
                return handle_signal(signr, &ka, &info, oldset, regs);
        }
 
index 46f4d6cc7fc9591ce7240887a05edadcd711c6f6..a8b7a5a56bb445b90f7116c3f418fd14b41a657b 100644 (file)
@@ -970,6 +970,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
                newsp = regs->gpr[1];
        newsp &= ~0xfUL;
 
+       /*
+        * Reenable the DABR before delivering the signal to
+        * user space. The DABR will have been cleared if it
+        * triggered inside the kernel.
+        */
+       if (current->thread.dabr)
+               set_dabr(current->thread.dabr);
+
        /* Whee!  Actually deliver the signal.  */
        if (ka.sa.sa_flags & SA_SIGINFO)
                ret = handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
index 0ed7ea721715be2197e4df3433ea081a09c75ff1..c8db993574ee84a0c6dd455f081a5788c9d51b22 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
 
index 29b6bd32e1f1a9e9de3c4897827761b5baa059ec..4f4eb0be3992eedf9b58160858efe3c96a366c93 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/vdso.h>
 
index 2b48bf1fb109fac828fc58839c12d86ee9c636af..07f1c1c650c89b83d6c4b7dd5ae0e2c660e63f3b 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 
        .text
index e0725b7b70034b71bdbbf4074a1122a0fc4834d3..d4a0ad28d534ead85150a30f5607cfbc48969ad7 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
 
index 18afd971c9d97930eaf11f002ee0eaba38af39bc..ed6e599ae8242a6a8ad992d0492a15a4cc3b8a1e 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/vdso.h>
 
index ed3f970ff05edffaa2698ece99b8d02a27c393ab..f6df8028570a795bab27779a06a18eb3785dc466 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
 #include <asm/vdso.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
 /*
index d9dc6f28d050050281ccc99e19e2d940de850abd..daf93885dcfab007cc73ddc7e446632d253b0055 100644 (file)
@@ -38,7 +38,7 @@ static void xics_mask_and_ack_irq(unsigned int irq);
 static void xics_end_irq(unsigned int irq);
 static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
 
-struct hw_interrupt_type xics_pic = {
+static struct hw_interrupt_type xics_pic = {
        .typename = " XICS     ",
        .startup = xics_startup,
        .enable = xics_enable_irq,
@@ -48,7 +48,7 @@ struct hw_interrupt_type xics_pic = {
        .set_affinity = xics_set_affinity
 };
 
-struct hw_interrupt_type xics_8259_pic = {
+static struct hw_interrupt_type xics_8259_pic = {
        .typename = " XICS/8259",
        .ack = xics_mask_and_ack_irq,
 };
@@ -89,9 +89,8 @@ static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
 static int xics_irq_8259_cascade = 0;
 static int xics_irq_8259_cascade_real = 0;
 static unsigned int default_server = 0xFF;
-/* also referenced in smp.c... */
-unsigned int default_distrib_server = 0;
-unsigned int interrupt_server_size = 8;
+static unsigned int default_distrib_server = 0;
+static unsigned int interrupt_server_size = 8;
 
 /*
  * XICS only has a single IPI, so encode the messages per CPU
@@ -99,10 +98,10 @@ unsigned int interrupt_server_size = 8;
 struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned;
 
 /* RTAS service tokens */
-int ibm_get_xive;
-int ibm_set_xive;
-int ibm_int_on;
-int ibm_int_off;
+static int ibm_get_xive;
+static int ibm_set_xive;
+static int ibm_int_on;
+static int ibm_int_off;
 
 typedef struct {
        int (*xirr_info_get)(int cpu);
@@ -284,16 +283,17 @@ static void xics_enable_irq(unsigned int virq)
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
                                DEFAULT_PRIORITY);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_set_xive "
-                      "returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_set_xive "
+                      "returned %d\n", irq, call_status);
+               printk("set_xive %x, server %x\n", ibm_set_xive, server);
                return;
        }
 
        /* Now unmask the interrupt (often a no-op) */
        call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_enable_irq: irq=%d: ibm_int_on "
-                      "returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_enable_irq: irq=%u: ibm_int_on "
+                      "returned %d\n", irq, call_status);
                return;
        }
 }
@@ -308,8 +308,8 @@ static void xics_disable_real_irq(unsigned int irq)
 
        call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_real_irq: irq=%d: "
-                      "ibm_int_off returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_disable_real_irq: irq=%u: "
+                      "ibm_int_off returned %d\n", irq, call_status);
                return;
        }
 
@@ -317,8 +317,8 @@ static void xics_disable_real_irq(unsigned int irq)
        /* Have to set XIVE to 0xff to be able to remove a slot */
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, 0xff);
        if (call_status != 0) {
-               printk(KERN_ERR "xics_disable_irq: irq=%d: ibm_set_xive(0xff)"
-                      " returned %x\n", irq, call_status);
+               printk(KERN_ERR "xics_disable_irq: irq=%u: ibm_set_xive(0xff)"
+                      " returned %d\n", irq, call_status);
                return;
        }
 }
@@ -380,7 +380,7 @@ int xics_get_irq(struct pt_regs *regs)
                if (irq == NO_IRQ)
                        irq = real_irq_to_virt_slowpath(vec);
                if (irq == NO_IRQ) {
-                       printk(KERN_ERR "Interrupt %d (real) is invalid,"
+                       printk(KERN_ERR "Interrupt %u (real) is invalid,"
                               " disabling it.\n", vec);
                        xics_disable_real_irq(vec);
                } else
@@ -622,7 +622,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
        status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive "
+               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,get-xive "
                       "returns %d\n", irq, status);
                return;
        }
@@ -641,7 +641,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
                                irq, newmask, xics_status[1]);
 
        if (status) {
-               printk(KERN_ERR "xics_set_affinity: irq=%d ibm,set-xive "
+               printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive "
                       "returns %d\n", irq, status);
                return;
        }
@@ -720,7 +720,7 @@ void xics_migrate_irqs_away(void)
 
                status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
                if (status) {
-                       printk(KERN_ERR "migrate_irqs_away: irq=%d "
+                       printk(KERN_ERR "migrate_irqs_away: irq=%u "
                                        "ibm,get-xive returns %d\n",
                                        virq, status);
                        goto unlock;
@@ -734,7 +734,7 @@ void xics_migrate_irqs_away(void)
                if (xics_status[0] != get_hard_smp_processor_id(cpu))
                        goto unlock;
 
-               printk(KERN_WARNING "IRQ %d affinity broken off cpu %u\n",
+               printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
                       virq, cpu);
 
                /* Reset affinity to all cpus */
index 6e8d8591708cbbc37e7a9dfe8fd9911774899705..7b9d4da5cf926e12ff1c9811242af1bc7f899662 100644 (file)
  * has a cmpxchg, and where atomic->value is an int holding
  * the value of the atomic (i.e. the high bits aren't used
  * for a lock or anything like that).
- *
- * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
- * if spinlocks are empty and thus atomic_dec_and_lock is defined
- * to be atomic_dec_and_test - in that case we don't need it
- * defined here as well.
  */
-
-#ifndef ATOMIC_DEC_AND_LOCK
 int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 {
        int counter;
@@ -52,4 +45,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 }
 
 EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif /* ATOMIC_DEC_AND_LOCK */
index ef70ef91abe26dfc9d21606a34f80d3d5f428892..033643ab69e0bfac4903c4544fbfc52f70ba8972 100644 (file)
 /* waiting for a spinlock... */
 #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 
-void __spin_yield(spinlock_t *lock)
+void __spin_yield(raw_spinlock_t *lock)
 {
        unsigned int lock_value, holder_cpu, yield_count;
        struct paca_struct *holder_paca;
 
-       lock_value = lock->lock;
+       lock_value = lock->slock;
        if (lock_value == 0)
                return;
        holder_cpu = lock_value & 0xffff;
@@ -38,7 +38,7 @@ void __spin_yield(spinlock_t *lock)
        if ((yield_count & 1) == 0)
                return;         /* virtual cpu is currently running */
        rmb();
-       if (lock->lock != lock_value)
+       if (lock->slock != lock_value)
                return;         /* something has changed */
 #ifdef CONFIG_PPC_ISERIES
        HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
@@ -54,7 +54,7 @@ void __spin_yield(spinlock_t *lock)
  * This turns out to be the same for read and write locks, since
  * we only know the holder if it is write-locked.
  */
-void __rw_yield(rwlock_t *rw)
+void __rw_yield(raw_rwlock_t *rw)
 {
        int lock_value;
        unsigned int holder_cpu, yield_count;
@@ -82,9 +82,9 @@ void __rw_yield(rwlock_t *rw)
 }
 #endif
 
-void spin_unlock_wait(spinlock_t *lock)
+void __raw_spin_unlock_wait(raw_spinlock_t *lock)
 {
-       while (lock->lock) {
+       while (lock->slock) {
                HMT_low();
                if (SHARED_PROCESSOR)
                        __spin_yield(lock);
@@ -92,4 +92,4 @@ void spin_unlock_wait(spinlock_t *lock)
        HMT_medium();
 }
 
-EXPORT_SYMBOL(spin_unlock_wait);
+EXPORT_SYMBOL(__raw_spin_unlock_wait);
index 772f0714a5b7d4be9231b362650c920c1c70cb9c..7fbc68bbb7391cef88ee614d2ec54f291f54c7dc 100644 (file)
@@ -77,6 +77,28 @@ static int store_updates_sp(struct pt_regs *regs)
        return 0;
 }
 
+static void do_dabr(struct pt_regs *regs, unsigned long error_code)
+{
+       siginfo_t info;
+
+       if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+                       11, SIGSEGV) == NOTIFY_STOP)
+               return;
+
+       if (debugger_dabr_match(regs))
+               return;
+
+       /* Clear the DABR */
+       set_dabr(0);
+
+       /* Deliver the signal to userspace */
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = TRAP_HWBKPT;
+       info.si_addr = (void __user *)regs->nip;
+       force_sig_info(SIGTRAP, &info, current);
+}
+
 /*
  * The error_code parameter is
  *  - DSISR for a non-SLB data access fault,
@@ -111,12 +133,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
        if (!user_mode(regs) && (address >= TASK_SIZE))
                return SIGSEGV;
 
-       if (error_code & DSISR_DABRMATCH) {
-               if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
-                                       11, SIGSEGV) == NOTIFY_STOP)
-                       return 0;
-               if (debugger_dabr_match(regs))
-                       return 0;
+       if (error_code & DSISR_DABRMATCH) {
+               do_dabr(regs, error_code);
+               return 0;
        }
 
        if (in_atomic() || mm == NULL) {
index 35eb49e1b8908d4c6c94580f45561f97e438c422..ee5a5d36bfa8e72ea3a01c44dcd95ee00d8e54d6 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/page.h>
 #include <asm/types.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cputable.h>
 
        .text
index 698d6b9ed6d19566d83a2299715f72a512ef96bb..a3a03da503bcbde0ed78b6611dbd42023e02618c 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/page.h>
 #include <asm/mmu.h>
 #include <asm/ppc_asm.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/cputable.h>
 
 /* void slb_allocate(unsigned long ea);
index 183c3e40025881daab3b80ec360a47f2d380af1e..02eb40dac0b304fbcab0b3cf0d136bc312a9eb79 100644 (file)
@@ -46,7 +46,6 @@ GSETSPR(287, pvr)
 GSETSPR(1008, hid0)
 GSETSPR(1009, hid1)
 GSETSPR(1010, iabr)
-GSETSPR(1013, dabr)
 GSETSPR(1023, pir)
 
 static inline void store_inst(void *p)
index 45908b10acd345970da83c6d5369fc850e6b072a..74e63a886a69ae4b9769cacd3b6f2df44bcec48d 100644 (file)
@@ -586,6 +586,8 @@ int xmon_dabr_match(struct pt_regs *regs)
 {
        if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
                return 0;
+       if (dabr.enabled == 0)
+               return 0;
        xmon_core(regs, 0);
        return 1;
 }
@@ -628,20 +630,6 @@ int xmon_fault_handler(struct pt_regs *regs)
        return 0;
 }
 
-/* On systems with a hypervisor, we can't set the DABR
-   (data address breakpoint register) directly. */
-static void set_controlled_dabr(unsigned long val)
-{
-#ifdef CONFIG_PPC_PSERIES
-       if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
-               int rc = plpar_hcall_norets(H_SET_DABR, val);
-               if (rc != H_Success)
-                       xmon_printf("Warning: setting DABR failed (%d)\n", rc);
-       } else
-#endif
-               set_dabr(val);
-}
-
 static struct bpt *at_breakpoint(unsigned long pc)
 {
        int i;
@@ -728,7 +716,7 @@ static void insert_bpts(void)
 static void insert_cpu_bpts(void)
 {
        if (dabr.enabled)
-               set_controlled_dabr(dabr.address | (dabr.enabled & 7));
+               set_dabr(dabr.address | (dabr.enabled & 7));
        if (iabr && cpu_has_feature(CPU_FTR_IABR))
                set_iabr(iabr->address
                         | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -756,7 +744,7 @@ static void remove_bpts(void)
 
 static void remove_cpu_bpts(void)
 {
-       set_controlled_dabr(0);
+       set_dabr(0);
        if (cpu_has_feature(CPU_FTR_IABR))
                set_iabr(0);
 }
index c1ea6bcb77ce82cdf88a7aa4c2f3bf50b581a793..98db30481d97eb211d1e767ca9701767e323dc09 100644 (file)
@@ -102,16 +102,6 @@ image: vmlinux
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-prepare: include/asm-$(ARCH)/offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/offsets.h
-
 # Don't use tabs in echo arguments
 define archhelp
   echo  '* image           - Kernel image for IPL ($(boot)/image)'
index 18610cea03a21d6d59bfb23224ecf1672678c7bc..ed877d0f27e6e038b12c24489ac1e3914d7ba478 100644 (file)
@@ -678,7 +678,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size
        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
        set_fs(old_fs);
        
-       if (!ret && offset && put_user(of, offset))
+       if (offset && put_user(of, offset))
                return -EFAULT;
                
        return ret;
index cbe7d6a2d02cdc36bf5ac511f41e4c16f60410fa..58fc7fbcb40e17d6150f171125e47bafde4f0591 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/errno.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
 
index fb77b72ab2627a3ae3f7988f037bbfc230029e62..d0c9ffaa25db7b02c0bb77c76097e2cdceee852c 100644 (file)
@@ -18,7 +18,7 @@
 #include <asm/errno.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
 
index 2710e66fefbaf04d7996212bbff1f769950522ed..55654b6e16dce24c38e6642b6ddd48724124f5b0 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
index 9a8263a153cbaf551c89878cb223cade9022164c..c9ff0404c875e15895ce794833c25adaf45bcb34 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
index 888b5596c195d5123a24b60099b46f2c6f3634aa..2dc14e9c83276818f95afa4d054e1f836fec4774 100644 (file)
@@ -36,7 +36,7 @@ _diag44(void)
 }
 
 void
-_raw_spin_lock_wait(spinlock_t *lp, unsigned int pc)
+_raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
 {
        int count = spin_retry;
 
@@ -53,7 +53,7 @@ _raw_spin_lock_wait(spinlock_t *lp, unsigned int pc)
 EXPORT_SYMBOL(_raw_spin_lock_wait);
 
 int
-_raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc)
+_raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
 {
        int count = spin_retry;
 
@@ -67,7 +67,7 @@ _raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc)
 EXPORT_SYMBOL(_raw_spin_trylock_retry);
 
 void
-_raw_read_lock_wait(rwlock_t *rw)
+_raw_read_lock_wait(raw_rwlock_t *rw)
 {
        unsigned int old;
        int count = spin_retry;
@@ -86,7 +86,7 @@ _raw_read_lock_wait(rwlock_t *rw)
 EXPORT_SYMBOL(_raw_read_lock_wait);
 
 int
-_raw_read_trylock_retry(rwlock_t *rw)
+_raw_read_trylock_retry(raw_rwlock_t *rw)
 {
        unsigned int old;
        int count = spin_retry;
@@ -102,7 +102,7 @@ _raw_read_trylock_retry(rwlock_t *rw)
 EXPORT_SYMBOL(_raw_read_trylock_retry);
 
 void
-_raw_write_lock_wait(rwlock_t *rw)
+_raw_write_lock_wait(raw_rwlock_t *rw)
 {
        int count = spin_retry;
 
@@ -119,7 +119,7 @@ _raw_write_lock_wait(rwlock_t *rw)
 EXPORT_SYMBOL(_raw_write_lock_wait);
 
 int
-_raw_write_trylock_retry(rwlock_t *rw)
+_raw_write_trylock_retry(raw_rwlock_t *rw)
 {
        int count = spin_retry;
 
index e8029ef42ef2d3c13f679d50626c6aaf0608508b..88fc94fe6488079667b482264787b40b0c3d2660 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <linux/errno.h>
 #include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
         .text
         .align 4
index 0ca56972f4f090501b46608fb0d6d41b0bfa732e..50219786fc7ac8bc86138594a4fd253c3a2048eb 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <linux/errno.h>
 #include <asm/lowcore.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
         .text
         .align 4
index b5635635b5ee7f8700b1b7137eba910941a34bab..4a3049080b4190cc61518d2625195e95d1737f65 100644 (file)
@@ -152,10 +152,10 @@ endif
        @touch $@
 
 
-prepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
+archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
 
 .PHONY: maketools FORCE
-maketools: include/asm-sh/asm-offsets.h include/linux/version.h FORCE
+maketools:  include/linux/version.h FORCE
        $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
 
 all: zImage
@@ -168,14 +168,7 @@ compressed: zImage
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-CLEAN_FILES += include/asm-sh/machtypes.h include/asm-sh/asm-offsets.h
-
-arch/sh/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                             include/asm-sh/.cpu include/asm-sh/.mach
-
-include/asm-sh/asm-offsets.h: arch/sh/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
+CLEAN_FILES += include/asm-sh/machtypes.h
 
 define archhelp
        @echo '  zImage                    - Compressed kernel image (arch/sh/boot/zImage)'
index ca91bb0f1f5c0dc9305259c833e62612d2b9f061..c0973f8d57bae3c6060a9f4e67ddf9a11adfef21 100644 (file)
@@ -37,13 +37,13 @@ static void end_maskreg_irq(unsigned int irq);
 
 /* hw_interrupt_type */
 static struct hw_interrupt_type maskreg_irq_type = {
-       " Mask Register",
-       startup_maskreg_irq,
-       shutdown_maskreg_irq,
-       enable_maskreg_irq,
-       disable_maskreg_irq,
-       mask_and_ack_maskreg,
-       end_maskreg_irq
+       .typename = " Mask Register",
+       .startup = startup_maskreg_irq,
+       .shutdown = shutdown_maskreg_irq,
+       .enable = enable_maskreg_irq,
+       .disable = disable_maskreg_irq,
+       .ack = mask_and_ack_maskreg,
+       .end = end_maskreg_irq
 };
 
 /* actual implementatin */
index 697144de741947ec191ce31835e3e05bbd0f723a..a9fde781b21acb8f5c185a5bd1fd881b9fc90efb 100644 (file)
@@ -37,10 +37,6 @@ static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
 static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
 static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
 
-#ifndef MAX
-#define MAX(a,b)    ((a)>(b)?(a):(b))
-#endif
-
 void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
 {
        u32 port, endport = baseport + nports;
@@ -57,7 +53,7 @@ void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
                addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
        }
 
-       for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+       for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
             port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
             port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
                pr_debug("    maphi[0x%x] = 0x%08x\n", port, addr);
@@ -80,7 +76,7 @@ void bigsur_port_unmap(u32 baseport, u32 nports)
                bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
        }
 
-       for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+       for (port = max_t(u32, baseport, BIGSUR_IOMAP_LO_THRESH);
             port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
             port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
                bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
index c188fc32dc9a8c4f1207d9e59cbc83a3b9178ff9..6ddbcc77244da4d81653baa2c6bb2a6bb838debd 100644 (file)
@@ -228,23 +228,23 @@ static void shutdown_bigsur_irq(unsigned int irq)
 
 /* Define the IRQ structures for the L1 and L2 IRQ types */
 static struct hw_interrupt_type bigsur_l1irq_type = {
-        "BigSur-CPLD-Level1-IRQ",
-        startup_bigsur_irq,
-        shutdown_bigsur_irq,
-        enable_bigsur_l1irq,
-        disable_bigsur_l1irq,
-        mask_and_ack_bigsur,
-        end_bigsur_irq
+       .typename  = "BigSur-CPLD-Level1-IRQ",
+       .startup = startup_bigsur_irq,
+       .shutdown = shutdown_bigsur_irq,
+       .enable = enable_bigsur_l1irq,
+       .disable = disable_bigsur_l1irq,
+       .ack = mask_and_ack_bigsur,
+       .end = end_bigsur_irq
 };
 
 static struct hw_interrupt_type bigsur_l2irq_type = {
-        "BigSur-CPLD-Level2-IRQ",
-        startup_bigsur_irq,
-        shutdown_bigsur_irq,
-        enable_bigsur_l2irq,
-        disable_bigsur_l2irq,
-        mask_and_ack_bigsur,
-        end_bigsur_irq
+       .typename  = "BigSur-CPLD-Level2-IRQ",
+       .startup = startup_bigsur_irq,
+       .shutdown  =shutdown_bigsur_irq,
+       .enable = enable_bigsur_l2irq,
+       .disable = disable_bigsur_l2irq,
+       .ack = mask_and_ack_bigsur,
+       .end = end_bigsur_irq
 };
 
 
index fa6cfe5a20a70512d43c5a6d7c0f4949710122d2..d1da0d844567f66156bff7632a4c73012e466fbe 100644 (file)
@@ -83,13 +83,13 @@ static void shutdown_cqreek_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type cqreek_irq_type = {
-       "CqREEK-IRQ",
-       startup_cqreek_irq,
-       shutdown_cqreek_irq,
-       enable_cqreek_irq,
-       disable_cqreek_irq,
-       mask_and_ack_cqreek,
-       end_cqreek_irq
+       .typename = "CqREEK-IRQ",
+       .startup = startup_cqreek_irq,
+       .shutdown = shutdown_cqreek_irq,
+       .enable = enable_cqreek_irq,
+       .disable = disable_cqreek_irq,
+       .ack = mask_and_ack_cqreek,
+       .end = end_cqreek_irq
 };
 
 int cqreek_has_ide, cqreek_has_isa;
index acd58489970f4c04ed585fc4b612ebddc9e1cc48..52d0ba39031b7215a1a9c62dc3af49461c6f817f 100644 (file)
@@ -39,13 +39,13 @@ static unsigned int startup_harp_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type harp_irq_type = {
-       "Harp-IRQ",
-       startup_harp_irq,
-       shutdown_harp_irq,
-       enable_harp_irq,
-       disable_harp_irq,
-       mask_and_ack_harp,
-       end_harp_irq
+       .typename = "Harp-IRQ",
+       .startup = startup_harp_irq,
+       .shutdown = shutdown_harp_irq,
+       .enable = enable_harp_irq,
+       .disable = disable_harp_irq,
+       .ack = mask_and_ack_harp,
+       .end = end_harp_irq
 };
 
 static void disable_harp_irq(unsigned int irq)
index 23adc6be71e728e6fc8a6bba7efdfaf1abe9061f..715e8feb3a68783cc8d1b4375beb632db0f21a7d 100644 (file)
@@ -86,13 +86,13 @@ static unsigned int startup_od_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type od_irq_type = {
-       "Overdrive-IRQ",
-       startup_od_irq,
-       shutdown_od_irq,
-       enable_od_irq,
-       disable_od_irq,
-       mask_and_ack_od,
-       end_od_irq
+       .typename = "Overdrive-IRQ",
+       .startup = startup_od_irq,
+       .shutdown = shutdown_od_irq,
+       .enable = enable_od_irq,
+       .disable = disable_od_irq,
+       .ack = mask_and_ack_od,
+       .end = end_od_irq
 };
 
 static void disable_od_irq(unsigned int irq)
index a7921f67a35fcc42bc352e9b89ca8f7e93e6a326..ed4c5b50ea45edc29cb77c57f0731dfeda251f47 100644 (file)
@@ -74,13 +74,13 @@ static void end_hs7751rvoip_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type hs7751rvoip_irq_type = {
-       "HS7751RVoIP IRQ",
-       startup_hs7751rvoip_irq,
-       shutdown_hs7751rvoip_irq,
-       enable_hs7751rvoip_irq,
-       disable_hs7751rvoip_irq,
-       ack_hs7751rvoip_irq,
-       end_hs7751rvoip_irq,
+       .typename =  "HS7751RVoIP IRQ",
+       .startup = startup_hs7751rvoip_irq,
+       .shutdown = shutdown_hs7751rvoip_irq,
+       .enable = enable_hs7751rvoip_irq,
+       .disable = disable_hs7751rvoip_irq,
+       .ack = ack_hs7751rvoip_irq,
+       .end = end_hs7751rvoip_irq,
 };
 
 static void make_hs7751rvoip_irq(unsigned int irq)
index 95717f4f1e2d024f6c4ec890c584c10df64996ab..d36c9374aed1dffc9daf9980a5a8439f3da2dd00 100644 (file)
@@ -88,13 +88,13 @@ static void end_rts7751r2d_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type rts7751r2d_irq_type = {
-       "RTS7751R2D IRQ",
-       startup_rts7751r2d_irq,
-       shutdown_rts7751r2d_irq,
-       enable_rts7751r2d_irq,
-       disable_rts7751r2d_irq,
-       ack_rts7751r2d_irq,
-       end_rts7751r2d_irq,
+       .typename = "RTS7751R2D IRQ",
+       .startup = startup_rts7751r2d_irq,
+       .shutdown = shutdown_rts7751r2d_irq,
+       .enable = enable_rts7751r2d_irq,
+       .disable = disable_rts7751r2d_irq,
+       .ack = ack_rts7751r2d_irq,
+       .end = end_rts7751r2d_irq,
 };
 
 static void make_rts7751r2d_irq(unsigned int irq)
index 5675a4134eee8e13cc749a4765eb3cf38bfc773a..7a2eb10edb563c4b108b35204528b536aa1d6e45 100644 (file)
@@ -35,13 +35,13 @@ static void end_systemh_irq(unsigned int irq);
 
 /* hw_interrupt_type */
 static struct hw_interrupt_type systemh_irq_type = {
-       " SystemH Register",
-       startup_systemh_irq,
-       shutdown_systemh_irq,
-       enable_systemh_irq,
-       disable_systemh_irq,
-       mask_and_ack_systemh,
-       end_systemh_irq
+       .typename = " SystemH Register",
+       .startup = startup_systemh_irq,
+       .shutdown = shutdown_systemh_irq,
+       .enable = enable_systemh_irq,
+       .disable = disable_systemh_irq,
+       .ack = mask_and_ack_systemh,
+       .end = end_systemh_irq
 };
 
 static unsigned int startup_systemh_irq(unsigned int irq)
index 1298883eca4bef862b0884fcdd7ae009f63ade23..1395c1e65da4546948548918473108d42ff0b4f6 100644 (file)
@@ -83,13 +83,13 @@ static unsigned int startup_microdev_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type microdev_irq_type = {
-       "MicroDev-IRQ",
-       startup_microdev_irq,
-       shutdown_microdev_irq,
-       enable_microdev_irq,
-       disable_microdev_irq,
-       mask_and_ack_microdev,
-       end_microdev_irq
+       .typename = "MicroDev-IRQ",
+       .startup = startup_microdev_irq,
+       .shutdown = shutdown_microdev_irq,
+       .enable = enable_microdev_irq,
+       .disable = disable_microdev_irq,
+       .ack = mask_and_ack_microdev,
+       .end = end_microdev_irq
 };
 
 static void disable_microdev_irq(unsigned int irq)
index 99ac709c550e920feeb2c241b3c739859bc7a08d..84cb142def0b150f7a463c9dc8f3ac79224b45d1 100644 (file)
@@ -48,10 +48,6 @@ static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP];
 static unsigned long   hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP];
 static unsigned char   hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP];
 
-#ifndef MAX
-#define MAX(a,b)    ((a)>(b)?(a):(b))
-#endif
-
 #define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
 
 void hd64465_port_map(unsigned short baseport, unsigned int nports,
@@ -71,7 +67,7 @@ void hd64465_port_map(unsigned short baseport, unsigned int nports,
            addr += (1<<(HD64465_IOMAP_LO_SHIFT));
        }
 
-       for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
+       for (port = max_t(unsigned int, baseport, HD64465_IOMAP_LO_THRESH);
             port < endport && port < HD64465_IOMAP_HI_THRESH ;
             port += (1<<HD64465_IOMAP_HI_SHIFT)) {
            DPRINTK("    maphi[0x%x] = 0x%08lx\n", port, addr);
@@ -95,7 +91,7 @@ void hd64465_port_unmap(unsigned short baseport, unsigned int nports)
            hd64465_iomap_lo[port>>HD64465_IOMAP_LO_SHIFT] = 0;
        }
 
-       for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ;
+       for (port = max_t(unsigned int, baseport, HD64465_IOMAP_LO_THRESH);
             port < endport && port < HD64465_IOMAP_HI_THRESH ;
             port += (1<<HD64465_IOMAP_HI_SHIFT)) {
            hd64465_iomap_hi[port>>HD64465_IOMAP_HI_SHIFT] = 0;
index 3079234cb65b30d319d72ddf349e6cb85ffcf418..1b6ac523b4584e7cf5518f992cb340d293859484 100644 (file)
@@ -87,13 +87,13 @@ static void shutdown_voyagergx_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type voyagergx_irq_type = {
-       "VOYAGERGX-IRQ",
-       startup_voyagergx_irq,
-       shutdown_voyagergx_irq,
-       enable_voyagergx_irq,
-       disable_voyagergx_irq,
-       mask_and_ack_voyagergx,
-       end_voyagergx_irq,
+       .typename = "VOYAGERGX-IRQ",
+       .startup = startup_voyagergx_irq,
+       .shutdown = shutdown_voyagergx_irq,
+       .enable = enable_voyagergx_irq,
+       .disable = disable_voyagergx_irq,
+       .ack = mask_and_ack_voyagergx,
+       .end = end_voyagergx_irq,
 };
 
 static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
index f76901e732fb801a268fe05cacfa5efd796f231a..a963d00a971e6533f4a7eaacf6c0dc3122c86fc6 100644 (file)
@@ -46,13 +46,13 @@ static unsigned int startup_imask_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type imask_irq_type = {
-       "SR.IMASK",
-       startup_imask_irq,
-       shutdown_imask_irq,
-       enable_imask_irq,
-       disable_imask_irq,
-       mask_and_ack_imask,
-       end_imask_irq
+       .typename = "SR.IMASK",
+       .startup = startup_imask_irq,
+       .shutdown = shutdown_imask_irq,
+       .enable = enable_imask_irq,
+       .disable = disable_imask_irq,
+       .ack = mask_and_ack_imask,
+       .end = end_imask_irq
 };
 
 void static inline set_interrupt_registers(int ip)
index 7ea3d2d030e5581e847b5d2f9484e5bd41e9a739..71f92096132b3228e373981a267a0900b919d3e5 100644 (file)
@@ -48,13 +48,13 @@ static unsigned int startup_ipr_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type ipr_irq_type = {
-       "IPR-IRQ",
-       startup_ipr_irq,
-       shutdown_ipr_irq,
-       enable_ipr_irq,
-       disable_ipr_irq,
-       mask_and_ack_ipr,
-       end_ipr_irq
+       .typename = "IPR-IRQ",
+       .startup = startup_ipr_irq,
+       .shutdown = shutdown_ipr_irq,
+       .enable = enable_ipr_irq,
+       .disable = disable_ipr_irq,
+       .ack = mask_and_ack_ipr,
+       .end = end_ipr_irq
 };
 
 static void disable_ipr_irq(unsigned int irq)
@@ -142,13 +142,13 @@ static unsigned int startup_pint_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type pint_irq_type = {
-       "PINT-IRQ",
-       startup_pint_irq,
-       shutdown_pint_irq,
-       enable_pint_irq,
-       disable_pint_irq,
-       mask_and_ack_pint,
-       end_pint_irq
+       .typename = "PINT-IRQ",
+       .startup = startup_pint_irq,
+       .shutdown = shutdown_pint_irq,
+       .enable = enable_pint_irq,
+       .disable = disable_pint_irq,
+       .ack = mask_and_ack_pint,
+       .end = end_pint_irq
 };
 
 static void disable_pint_irq(unsigned int irq)
index 099ebbf897457a5b606c9f3acae891d0d717a6b8..f6b16ba01932f89929812c088a7d8808f2c5aa87 100644 (file)
@@ -48,13 +48,13 @@ static unsigned int startup_intc2_irq(unsigned int irq)
 }
 
 static struct hw_interrupt_type intc2_irq_type = {
-       "INTC2-IRQ",
-       startup_intc2_irq,
-       shutdown_intc2_irq,
-       enable_intc2_irq,
-       disable_intc2_irq,
-       mask_and_ack_intc2,
-       end_intc2_irq
+       .typename = "INTC2-IRQ",
+       .startup = startup_intc2_irq,
+       .shutdown = shutdown_intc2_irq,
+       .enable = enable_intc2_irq,
+       .disable = disable_intc2_irq,
+       .ack = mask_and_ack_intc2,
+       .end = end_intc2_irq
 };
 
 static void disable_intc2_irq(unsigned int irq)
index b4fd8e13fea99541a31b53456c0fe93bd78c1395..8ca57ffa2b709f57cc23453cc1dd0c293a558ffa 100644 (file)
@@ -73,11 +73,7 @@ compressed: zImage
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-prepare: include/asm-$(ARCH)/asm-offsets.h arch/$(ARCH)/lib/syscalltab.h
-
-include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
-                                  include/asm include/linux/version.h
-       $(call filechk,gen-asm-offsets)
+archprepare: arch/$(ARCH)/lib/syscalltab.h
 
 define filechk_gen-syscalltab
        (set -e; \
@@ -108,7 +104,7 @@ endef
 arch/$(ARCH)/lib/syscalltab.h: arch/sh64/kernel/syscalls.S
        $(call filechk,gen-syscalltab)
 
-CLEAN_FILES += include/asm-$(ARCH)/asm-offsets.h arch/$(ARCH)/lib/syscalltab.h
+CLEAN_FILES += arch/$(ARCH)/lib/syscalltab.h
 
 define archhelp
        @echo '  zImage                    - Compressed kernel image (arch/sh64/boot/zImage)'
index 43f88f3a78b0d219c5910560d0f6eefe0024b669..fc99bf4e362c9dfca4dada4ff45263baa3f46a08 100644 (file)
@@ -107,13 +107,13 @@ static void mask_and_ack_intc(unsigned int);
 static void end_intc_irq(unsigned int irq);
 
 static struct hw_interrupt_type intc_irq_type = {
-       "INTC",
-       startup_intc_irq,
-       shutdown_intc_irq,
-       enable_intc_irq,
-       disable_intc_irq,
-       mask_and_ack_intc,
-       end_intc_irq
+       .typename = "INTC",
+       .startup = startup_intc_irq,
+       .shutdown = shutdown_intc_irq,
+       .enable = enable_intc_irq,
+       .disable = disable_intc_irq,
+       .ack = mask_and_ack_intc,
+       .end = end_intc_irq
 };
 
 static int irlm;               /* IRL mode */
index 7b3bbaf083a69eba5eb524d56a0890d3112a24c5..dea48f6cff38be962d2c9f6cb7a12d251d4317fb 100644 (file)
@@ -59,17 +59,7 @@ image tftpboot.img: vmlinux
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-prepare: include/asm-$(ARCH)/asm_offsets.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h       \
-               arch/$(ARCH)/kernel/asm-offsets.s       \
-               arch/$(ARCH)/boot/System.map
+CLEAN_FILES += arch/$(ARCH)/boot/System.map
 
 # Don't use tabs in echo arguments.
 define archhelp
index b448166f5da95ee75da8548f255dfe0052b34be5..03ecb4e4614e01858a0cfecfdfa9071ce60c7e23 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/kgdb.h>
 #include <asm/contregs.h>
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/psr.h>
 #include <asm/vaddrs.h>
 #include <asm/memreg.h>
index 3a867fc19927429b2aea4b9605a61db8ef8f489c..136e37c53d49fd0ff26005b4ed3dea5a029bbe17 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/errno.h>
 #include <asm/winmacro.h>
 #include <asm/thread_info.h>
index 5d974a2b735a9ac354295ec6e4870cfb85049e12..f84809333624aae07d323e3b1577bc0ce5ddfb74 100644 (file)
@@ -114,17 +114,7 @@ DOT_ALIAS2(unsigned, urem, unsigned, unsigned)
 /* used by various drivers */
 EXPORT_SYMBOL(sparc_cpu_model);
 EXPORT_SYMBOL(kernel_thread);
-#ifdef CONFIG_DEBUG_SPINLOCK
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(_do_spin_lock);
-EXPORT_SYMBOL(_do_spin_unlock);
-EXPORT_SYMBOL(_spin_trylock);
-EXPORT_SYMBOL(_do_read_lock);
-EXPORT_SYMBOL(_do_read_unlock);
-EXPORT_SYMBOL(_do_write_lock);
-EXPORT_SYMBOL(_do_write_unlock);
-#endif
-#else
 // XXX find what uses (or used) these.
 EXPORT_SYMBOL(___rw_read_enter);
 EXPORT_SYMBOL(___rw_read_exit);
index 2296ff9dc47aa67c1af4c90a160317621aa59a35..fa5006946062134462f64f553d58d94f142f7501 100644 (file)
@@ -9,5 +9,3 @@ lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
         strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
         copy_user.o locks.o atomic.o atomic32.o bitops.o \
         lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
-
-lib-$(CONFIG_DEBUG_SPINLOCK) +=        debuglocks.o
index 19724c5800a79e48c23704e03af3668a691bb332..2e64e8c3e8e54c1aafbe66e34d3d64cf0f96f895 100644 (file)
@@ -20,7 +20,7 @@ spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
 
 #else /* SMP */
 
-static spinlock_t dummy = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dummy);
 #define ATOMIC_HASH_SIZE       1
 #define ATOMIC_HASH(a)         (&dummy)
 
diff --git a/arch/sparc/lib/debuglocks.c b/arch/sparc/lib/debuglocks.c
deleted file mode 100644 (file)
index fb18235..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/* $Id: debuglocks.c,v 1.11 2001/09/20 00:35:31 davem Exp $
- * debuglocks.c: Debugging versions of SMP locking primitives.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1998-99 Anton Blanchard (anton@progsoc.uts.edu.au)
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/threads.h>     /* For NR_CPUS */
-#include <linux/spinlock.h>
-#include <asm/psr.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-
-/* Some notes on how these debugging routines work.  When a lock is acquired
- * an extra debugging member lock->owner_pc is set to the caller of the lock
- * acquisition routine.  Right before releasing a lock, the debugging program
- * counter is cleared to zero.
- *
- * Furthermore, since PC's are 4 byte aligned on Sparc, we stuff the CPU
- * number of the owner in the lowest two bits.
- */
-
-#define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
-
-static inline void show(char *str, spinlock_t *lock, unsigned long caller)
-{
-       int cpu = smp_processor_id();
-
-       printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
-               lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
-}
-
-static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
-{
-       int cpu = smp_processor_id();
-
-       printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", str,
-               lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
-}
-
-static inline void show_write(char *str, rwlock_t *lock, unsigned long caller)
-{
-       int cpu = smp_processor_id();
-       int i;
-
-       printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)", str,
-               lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
-
-       for(i = 0; i < NR_CPUS; i++)
-               printk(" reader[%d]=%08lx", i, lock->reader_pc[i]);
-
-       printk("\n");
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-void _do_spin_lock(spinlock_t *lock, char *str)
-{
-       unsigned long caller;
-       unsigned long val;
-       int cpu = smp_processor_id();
-       int stuck = INIT_STUCK;
-
-       STORE_CALLER(caller);
-
-again:
-       __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
-       if(val) {
-               while(lock->lock) {
-                       if (!--stuck) {
-                               show(str, lock, caller);
-                               stuck = INIT_STUCK;
-                       }
-                       barrier();
-               }
-               goto again;
-       }
-       lock->owner_pc = (cpu & 3) | (caller & ~3);
-}
-
-int _spin_trylock(spinlock_t *lock)
-{
-       unsigned long val;
-       unsigned long caller;
-       int cpu = smp_processor_id();
-
-       STORE_CALLER(caller);
-
-       __asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
-       if(!val) {
-               /* We got it, record our identity for debugging. */
-               lock->owner_pc = (cpu & 3) | (caller & ~3);
-       }
-       return val == 0;
-}
-
-void _do_spin_unlock(spinlock_t *lock)
-{
-       lock->owner_pc = 0;
-       barrier();
-       lock->lock = 0;
-}
-
-void _do_read_lock(rwlock_t *rw, char *str)
-{
-       unsigned long caller;
-       unsigned long val;
-       int cpu = smp_processor_id();
-       int stuck = INIT_STUCK;
-
-       STORE_CALLER(caller);
-
-wlock_again:
-       __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-       if(val) {
-               while(rw->lock & 0xff) {
-                       if (!--stuck) {
-                               show_read(str, rw, caller);
-                               stuck = INIT_STUCK;
-                       }
-                       barrier();
-               }
-               goto wlock_again;
-       }
-
-       rw->reader_pc[cpu] = caller;
-       barrier();
-       rw->lock++;
-}
-
-void _do_read_unlock(rwlock_t *rw, char *str)
-{
-       unsigned long caller;
-       unsigned long val;
-       int cpu = smp_processor_id();
-       int stuck = INIT_STUCK;
-
-       STORE_CALLER(caller);
-
-wlock_again:
-       __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-       if(val) {
-               while(rw->lock & 0xff) {
-                       if (!--stuck) {
-                               show_read(str, rw, caller);
-                               stuck = INIT_STUCK;
-                       }
-                       barrier();
-               }
-               goto wlock_again;
-       }
-
-       rw->reader_pc[cpu] = 0;
-       barrier();
-       rw->lock -= 0x1ff;
-}
-
-void _do_write_lock(rwlock_t *rw, char *str)
-{
-       unsigned long caller;
-       unsigned long val;
-       int cpu = smp_processor_id();
-       int stuck = INIT_STUCK;
-
-       STORE_CALLER(caller);
-
-wlock_again:
-       __asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-       if(val) {
-wlock_wait:
-               while(rw->lock) {
-                       if (!--stuck) {
-                               show_write(str, rw, caller);
-                               stuck = INIT_STUCK;
-                       }
-                       barrier();
-               }
-               goto wlock_again;
-       }
-
-       if (rw->lock & ~0xff) {
-               *(((unsigned char *)&rw->lock)+3) = 0;
-               barrier();
-               goto wlock_wait;
-       }
-
-       barrier();
-       rw->owner_pc = (cpu & 3) | (caller & ~3);
-}
-
-void _do_write_unlock(rwlock_t *rw)
-{
-       rw->owner_pc = 0;
-       barrier();
-       rw->lock = 0;
-}
-
-#endif /* SMP */
index 54b8e764b0423f55ada9bdf04de650eef6e9f4bd..a231cca37216a84344e9d90bf67f372a53aa6443 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/psr.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/asi.h>
 #include <asm/page.h>
 #include <asm/pgtsrmmu.h>
index 2dcaa5ac1a38dfc15fa83dad562c4aac8d1fe3bd..cd90f3fdc4e7a3e1f1bcd7b5bf5b027862ca5d7a 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/asi.h>
 #include <asm/page.h>
 #include <asm/pgtsrmmu.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
        .text
        .align  4
index 8acd1787fde21ab0cae9b13dc34d78dc2c833e4c..697af617594ae24851a7a98336afb3240589f938 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/config.h>
 #include <asm/ptrace.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/psr.h>
 #include <asm/asi.h>
 #include <asm/page.h>
index f58712d26bf52e06cd4e90f6bc48bb3ccb617d05..3cbd6de18dde0bfc3891f4c8303edae287700922 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/psr.h>
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/asi.h>
 #include <asm/mxcc.h>
 #include <asm/page.h>
diff --git a/arch/sparc64/kernel/asm-offsets.c b/arch/sparc64/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..9e26311
--- /dev/null
@@ -0,0 +1 @@
+/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */
index 66255434128a2e6ebf6b144d5d030003fe4ebaca..7d10b03970919c63b6d1c1dd138b203f6fa42568 100644 (file)
@@ -607,11 +607,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
        struct thread_info *t = p->thread_info;
        char *child_trap_frame;
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-       p->thread.smp_lock_count = 0;
-       p->thread.smp_lock_pc = 0;
-#endif
-
        /* Calculate offset to stack_frame & pt_regs */
        child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
        memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ));
index 7d9a0f6c437dcc60dba88b30afe33af1dafcc550..cbb5e59824e569f68757dc220baed881159b9b54 100644 (file)
@@ -115,17 +115,12 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data);
 
 /* used by various drivers */
 #ifdef CONFIG_SMP
-#ifndef CONFIG_DEBUG_SPINLOCK
 /* Out of line rw-locking implementation. */
 EXPORT_SYMBOL(__read_lock);
 EXPORT_SYMBOL(__read_unlock);
 EXPORT_SYMBOL(__write_lock);
 EXPORT_SYMBOL(__write_unlock);
 EXPORT_SYMBOL(__write_trylock);
-/* Out of line spin-locking implementation. */
-EXPORT_SYMBOL(_raw_spin_lock);
-EXPORT_SYMBOL(_raw_spin_lock_flags);
-#endif
 
 /* Hard IRQ locking */
 EXPORT_SYMBOL(synchronize_irq);
index 40dbeec7e5d6a8ed75006dd2873e0d40e019b29e..d968aebe83b282319fefb194dd942b3614a67764 100644 (file)
@@ -14,7 +14,6 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
         copy_in_user.o user_fixup.o memmove.o \
         mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o
 
-lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
 
 obj-y += iomap.o
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
deleted file mode 100644 (file)
index f5f0b55..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $
- * debuglocks.c: Debugging versions of SMP locking primitives.
- *
- * Copyright (C) 1998 David S. Miller (davem@redhat.com)
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-
-static inline void show (char *str, spinlock_t *lock, unsigned long caller)
-{
-       int cpu = smp_processor_id();
-
-       printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n",
-              str, lock, cpu, (unsigned int) caller,
-              lock->owner_pc, lock->owner_cpu);
-}
-
-static inline void show_read (char *str, rwlock_t *lock, unsigned long caller)
-{
-       int cpu = smp_processor_id();
-
-       printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n",
-              str, lock, cpu, (unsigned int) caller,
-              lock->writer_pc, lock->writer_cpu);
-}
-
-static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
-{
-       int cpu = smp_processor_id();
-       int i;
-
-       printk("%s(%p) CPU#%d stuck at %08x\n",
-              str, lock, cpu, (unsigned int) caller);
-       printk("Writer: PC(%08x):CPU(%x)\n",
-              lock->writer_pc, lock->writer_cpu);
-       printk("Readers:");
-       for (i = 0; i < NR_CPUS; i++)
-               if (lock->reader_pc[i])
-                       printk(" %d[%08x]", i, lock->reader_pc[i]);
-       printk("\n");
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller)
-{
-       unsigned long val;
-       int stuck = INIT_STUCK;
-       int cpu = get_cpu();
-       int shown = 0;
-
-again:
-       __asm__ __volatile__("ldstub [%1], %0"
-                            : "=r" (val)
-                            : "r" (&(lock->lock))
-                            : "memory");
-       membar_storeload_storestore();
-       if (val) {
-               while (lock->lock) {
-                       if (!--stuck) {
-                               if (shown++ <= 2)
-                                       show(str, lock, caller);
-                               stuck = INIT_STUCK;
-                       }
-                       rmb();
-               }
-               goto again;
-       }
-       lock->owner_pc = ((unsigned int)caller);
-       lock->owner_cpu = cpu;
-       current->thread.smp_lock_count++;
-       current->thread.smp_lock_pc = ((unsigned int)caller);
-
-       put_cpu();
-}
-
-int _do_spin_trylock(spinlock_t *lock, unsigned long caller)
-{
-       unsigned long val;
-       int cpu = get_cpu();
-
-       __asm__ __volatile__("ldstub [%1], %0"
-                            : "=r" (val)
-                            : "r" (&(lock->lock))
-                            : "memory");
-       membar_storeload_storestore();
-       if (!val) {
-               lock->owner_pc = ((unsigned int)caller);
-               lock->owner_cpu = cpu;
-               current->thread.smp_lock_count++;
-               current->thread.smp_lock_pc = ((unsigned int)caller);
-       }
-
-       put_cpu();
-
-       return val == 0;
-}
-
-void _do_spin_unlock(spinlock_t *lock)
-{
-       lock->owner_pc = 0;
-       lock->owner_cpu = NO_PROC_ID;
-       membar_storestore_loadstore();
-       lock->lock = 0;
-       current->thread.smp_lock_count--;
-}
-
-/* Keep INIT_STUCK the same... */
-
-void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller)
-{
-       unsigned long val;
-       int stuck = INIT_STUCK;
-       int cpu = get_cpu();
-       int shown = 0;
-
-wlock_again:
-       /* Wait for any writer to go away.  */
-       while (((long)(rw->lock)) < 0) {
-               if (!--stuck) {
-                       if (shown++ <= 2)
-                               show_read(str, rw, caller);
-                       stuck = INIT_STUCK;
-               }
-               rmb();
-       }
-       /* Try once to increment the counter.  */
-       __asm__ __volatile__(
-"      ldx             [%0], %%g1\n"
-"      brlz,a,pn       %%g1, 2f\n"
-"       mov            1, %0\n"
-"      add             %%g1, 1, %%g7\n"
-"      casx            [%0], %%g1, %%g7\n"
-"      sub             %%g1, %%g7, %0\n"
-"2:"   : "=r" (val)
-       : "0" (&(rw->lock))
-       : "g1", "g7", "memory");
-       membar_storeload_storestore();
-       if (val)
-               goto wlock_again;
-       rw->reader_pc[cpu] = ((unsigned int)caller);
-       current->thread.smp_lock_count++;
-       current->thread.smp_lock_pc = ((unsigned int)caller);
-
-       put_cpu();
-}
-
-void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller)
-{
-       unsigned long val;
-       int stuck = INIT_STUCK;
-       int cpu = get_cpu();
-       int shown = 0;
-
-       /* Drop our identity _first_. */
-       rw->reader_pc[cpu] = 0;
-       current->thread.smp_lock_count--;
-runlock_again:
-       /* Spin trying to decrement the counter using casx.  */
-       __asm__ __volatile__(
-"      membar  #StoreLoad | #LoadLoad\n"
-"      ldx     [%0], %%g1\n"
-"      sub     %%g1, 1, %%g7\n"
-"      casx    [%0], %%g1, %%g7\n"
-"      membar  #StoreLoad | #StoreStore\n"
-"      sub     %%g1, %%g7, %0\n"
-       : "=r" (val)
-       : "0" (&(rw->lock))
-       : "g1", "g7", "memory");
-       if (val) {
-               if (!--stuck) {
-                       if (shown++ <= 2)
-                               show_read(str, rw, caller);
-                       stuck = INIT_STUCK;
-               }
-               goto runlock_again;
-       }
-
-       put_cpu();
-}
-
-void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller)
-{
-       unsigned long val;
-       int stuck = INIT_STUCK;
-       int cpu = get_cpu();
-       int shown = 0;
-
-wlock_again:
-       /* Spin while there is another writer. */
-       while (((long)rw->lock) < 0) {
-               if (!--stuck) {
-                       if (shown++ <= 2)
-                               show_write(str, rw, caller);
-                       stuck = INIT_STUCK;
-               }
-               rmb();
-       }
-
-       /* Try to acuire the write bit.  */
-       __asm__ __volatile__(
-"      mov     1, %%g3\n"
-"      sllx    %%g3, 63, %%g3\n"
-"      ldx     [%0], %%g1\n"
-"      brlz,pn %%g1, 1f\n"
-"       or     %%g1, %%g3, %%g7\n"
-"      casx    [%0], %%g1, %%g7\n"
-"      membar  #StoreLoad | #StoreStore\n"
-"      ba,pt   %%xcc, 2f\n"
-"       sub    %%g1, %%g7, %0\n"
-"1:    mov     1, %0\n"
-"2:"   : "=r" (val)
-       : "0" (&(rw->lock))
-       : "g3", "g1", "g7", "memory");
-       if (val) {
-               /* We couldn't get the write bit. */
-               if (!--stuck) {
-                       if (shown++ <= 2)
-                               show_write(str, rw, caller);
-                       stuck = INIT_STUCK;
-               }
-               goto wlock_again;
-       }
-       if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
-               /* Readers still around, drop the write
-                * lock, spin, and try again.
-                */
-               if (!--stuck) {
-                       if (shown++ <= 2)
-                               show_write(str, rw, caller);
-                       stuck = INIT_STUCK;
-               }
-               __asm__ __volatile__(
-"              mov     1, %%g3\n"
-"              sllx    %%g3, 63, %%g3\n"
-"1:            ldx     [%0], %%g1\n"
-"              andn    %%g1, %%g3, %%g7\n"
-"              casx    [%0], %%g1, %%g7\n"
-"              cmp     %%g1, %%g7\n"
-"              membar  #StoreLoad | #StoreStore\n"
-"              bne,pn  %%xcc, 1b\n"
-"               nop"
-               : /* no outputs */
-               : "r" (&(rw->lock))
-               : "g3", "g1", "g7", "cc", "memory");
-               while(rw->lock != 0) {
-                       if (!--stuck) {
-                               if (shown++ <= 2)
-                                       show_write(str, rw, caller);
-                               stuck = INIT_STUCK;
-                       }
-                       rmb();
-               }
-               goto wlock_again;
-       }
-
-       /* We have it, say who we are. */
-       rw->writer_pc = ((unsigned int)caller);
-       rw->writer_cpu = cpu;
-       current->thread.smp_lock_count++;
-       current->thread.smp_lock_pc = ((unsigned int)caller);
-
-       put_cpu();
-}
-
-void _do_write_unlock(rwlock_t *rw, unsigned long caller)
-{
-       unsigned long val;
-       int stuck = INIT_STUCK;
-       int shown = 0;
-
-       /* Drop our identity _first_ */
-       rw->writer_pc = 0;
-       rw->writer_cpu = NO_PROC_ID;
-       current->thread.smp_lock_count--;
-wlock_again:
-       __asm__ __volatile__(
-"      membar  #StoreLoad | #LoadLoad\n"
-"      mov     1, %%g3\n"
-"      sllx    %%g3, 63, %%g3\n"
-"      ldx     [%0], %%g1\n"
-"      andn    %%g1, %%g3, %%g7\n"
-"      casx    [%0], %%g1, %%g7\n"
-"      membar  #StoreLoad | #StoreStore\n"
-"      sub     %%g1, %%g7, %0\n"
-       : "=r" (val)
-       : "0" (&(rw->lock))
-       : "g3", "g1", "g7", "memory");
-       if (val) {
-               if (!--stuck) {
-                       if (shown++ <= 2)
-                               show_write("write_unlock", rw, caller);
-                       stuck = INIT_STUCK;
-               }
-               goto wlock_again;
-       }
-}
-
-int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller)
-{
-       unsigned long val;
-       int cpu = get_cpu();
-
-       /* Try to acuire the write bit.  */
-       __asm__ __volatile__(
-"      mov     1, %%g3\n"
-"      sllx    %%g3, 63, %%g3\n"
-"      ldx     [%0], %%g1\n"
-"      brlz,pn %%g1, 1f\n"
-"       or     %%g1, %%g3, %%g7\n"
-"      casx    [%0], %%g1, %%g7\n"
-"      membar  #StoreLoad | #StoreStore\n"
-"      ba,pt   %%xcc, 2f\n"
-"       sub    %%g1, %%g7, %0\n"
-"1:    mov     1, %0\n"
-"2:"   : "=r" (val)
-       : "0" (&(rw->lock))
-       : "g3", "g1", "g7", "memory");
-
-       if (val) {
-               put_cpu();
-               return 0;
-       }
-
-       if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) {
-               /* Readers still around, drop the write
-                * lock, return failure.
-                */
-               __asm__ __volatile__(
-"              mov     1, %%g3\n"
-"              sllx    %%g3, 63, %%g3\n"
-"1:            ldx     [%0], %%g1\n"
-"              andn    %%g1, %%g3, %%g7\n"
-"              casx    [%0], %%g1, %%g7\n"
-"              cmp     %%g1, %%g7\n"
-"              membar  #StoreLoad | #StoreStore\n"
-"              bne,pn  %%xcc, 1b\n"
-"               nop"
-               : /* no outputs */
-               : "r" (&(rw->lock))
-               : "g3", "g1", "g7", "cc", "memory");
-
-               put_cpu();
-
-               return 0;
-       }
-
-       /* We have it, say who we are. */
-       rw->writer_pc = ((unsigned int)caller);
-       rw->writer_cpu = cpu;
-       current->thread.smp_lock_count++;
-       current->thread.smp_lock_pc = ((unsigned int)caller);
-
-       put_cpu();
-
-       return 1;
-}
-
-#endif /* CONFIG_SMP */
index cac0a1cf0050b5e55cf23a13f1d1504b5d1a0d0d..be0a054e3ed6b1d3c22b652978a56d916aa25c0f 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/netdevice.h>
 #include <linux/mtio.h>
 #include <linux/time.h>
+#include <linux/rcupdate.h>
 #include <linux/compat.h>
 
 #include <net/sock.h>
@@ -293,16 +294,18 @@ static struct module_info {
 static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg)
 {
        struct inode *ino;
+       struct fdtable *fdt;
        /* I wonder which of these tests are superfluous... --patrik */
-       spin_lock(&current->files->file_lock);
-       if (! current->files->fd[fd] ||
-           ! current->files->fd[fd]->f_dentry ||
-           ! (ino = current->files->fd[fd]->f_dentry->d_inode) ||
+       rcu_read_lock();
+       fdt = files_fdtable(current->files);
+       if (! fdt->fd[fd] ||
+           ! fdt->fd[fd]->f_dentry ||
+           ! (ino = fdt->fd[fd]->f_dentry->d_inode) ||
            ! S_ISSOCK(ino->i_mode)) {
-               spin_unlock(&current->files->file_lock);
+               rcu_read_unlock();
                return TBADF;
        }
-       spin_unlock(&current->files->file_lock);
+       rcu_read_unlock();
        
        switch (cmd & 0xff) {
        case 109: /* SI_SOCKPARAMS */
index 022c80f4339233add3d1c156028506b5aa53cdbc..aaad29c35c83870a4a65cc710e8535765c27279d 100644 (file)
@@ -143,9 +143,11 @@ static struct T_primsg *timod_mkctl(int size)
 static void timod_wake_socket(unsigned int fd)
 {
        struct socket *sock;
+       struct fdtable *fdt;
 
        SOLD("wakeing socket");
-       sock = SOCKET_I(current->files->fd[fd]->f_dentry->d_inode);
+       fdt = files_fdtable(current->files);
+       sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode);
        wake_up_interruptible(&sock->wait);
        read_lock(&sock->sk->sk_callback_lock);
        if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
@@ -157,9 +159,11 @@ static void timod_wake_socket(unsigned int fd)
 static void timod_queue(unsigned int fd, struct T_primsg *it)
 {
        struct sol_socket_struct *sock;
+       struct fdtable *fdt;
 
        SOLD("queuing primsg");
-       sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
+       fdt = files_fdtable(current->files);
+       sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
        it->next = sock->pfirst;
        sock->pfirst = it;
        if (!sock->plast)
@@ -171,9 +175,11 @@ static void timod_queue(unsigned int fd, struct T_primsg *it)
 static void timod_queue_end(unsigned int fd, struct T_primsg *it)
 {
        struct sol_socket_struct *sock;
+       struct fdtable *fdt;
 
        SOLD("queuing primsg at end");
-       sock = (struct sol_socket_struct *)current->files->fd[fd]->private_data;
+       fdt = files_fdtable(current->files);
+       sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data;
        it->next = NULL;
        if (sock->plast)
                sock->plast->next = it;
@@ -344,6 +350,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
        char *buf;
        struct file *filp;
        struct inode *ino;
+       struct fdtable *fdt;
        struct sol_socket_struct *sock;
        mm_segment_t old_fs = get_fs();
        long args[6];
@@ -351,7 +358,9 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len,
                (int (*)(int, unsigned long __user *))SYS(socketcall);
        int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) =
                (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto);
-       filp = current->files->fd[fd];
+
+       fdt = files_fdtable(current->files);
+       filp = fdt->fd[fd];
        ino = filp->f_dentry->d_inode;
        sock = (struct sol_socket_struct *)filp->private_data;
        SOLD("entry");
@@ -620,6 +629,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
        int oldflags;
        struct file *filp;
        struct inode *ino;
+       struct fdtable *fdt;
        struct sol_socket_struct *sock;
        struct T_unitdata_ind udi;
        mm_segment_t old_fs = get_fs();
@@ -632,7 +642,8 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us
        
        SOLD("entry");
        SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p));
-       filp = current->files->fd[fd];
+       fdt = files_fdtable(current->files);
+       filp = fdt->fd[fd];
        ino = filp->f_dentry->d_inode;
        sock = (struct sol_socket_struct *)filp->private_data;
        SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL));
@@ -844,12 +855,14 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
        int __user *flgptr;
        int flags;
        int error = -EBADF;
+       struct fdtable *fdt;
 
        SOLD("entry");
        lock_kernel();
        if(fd >= NR_OPEN) goto out;
 
-       filp = current->files->fd[fd];
+       fdt = files_fdtable(current->files);
+       filp = fdt->fd[fd];
        if(!filp) goto out;
 
        ino = filp->f_dentry->d_inode;
@@ -910,12 +923,14 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
        struct strbuf ctl, dat;
        int flags = (int) arg3;
        int error = -EBADF;
+       struct fdtable *fdt;
 
        SOLD("entry");
        lock_kernel();
        if(fd >= NR_OPEN) goto out;
 
-       filp = current->files->fd[fd];
+       fdt = files_fdtable(current->files);
+       filp = fdt->fd[fd];
        if(!filp) goto out;
 
        ino = filp->f_dentry->d_inode;
index b15f6048caae839cbde7e8fe02ffc8041dbdfc78..ce987266dac6206afbdaf85c974080578075f911 100644 (file)
@@ -103,12 +103,11 @@ endef
 
 ifneq ($(KBUILD_SRC),)
 $(shell mkdir -p $(ARCH_DIR) && ln -fsn $(srctree)/$(ARCH_DIR)/Kconfig.$(SUBARCH) $(ARCH_DIR)/Kconfig.arch)
-CLEAN_FILES += $(ARCH_DIR)/Kconfig.arch
 else
 $(shell cd $(ARCH_DIR) && ln -sf Kconfig.$(SUBARCH) Kconfig.arch)
 endif
 
-prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
+archprepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
 LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -144,14 +143,14 @@ endef
 #TT or skas makefiles and don't clean skas_ptregs.h.
 CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
        $(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h \
-       $(ARCH_DIR)/include/user_constants.h
+       $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/Kconfig.arch
 
 MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
-       $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os \
-       $(ARCH_DIR)/Kconfig.arch
+       $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
 
 archclean:
        $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util
+       $(Q)$(MAKE) $(clean)=$(ARCH_DIR)/os-$(OS)/util
        @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
                -o -name '*.gcov' \) -type f -print | xargs rm -f
 
@@ -197,6 +196,22 @@ define filechk_umlconfig
        sed 's/ CONFIG/ UML_CONFIG/'
 endef
 
+define filechk_gen-asm-offsets
+        (set -e; \
+         echo "#ifndef __ASM_OFFSETS_H__"; \
+         echo "#define __ASM_OFFSETS_H__"; \
+         echo "/*"; \
+         echo " * DO NOT MODIFY."; \
+         echo " *"; \
+         echo " * This file was generated by arch/$(ARCH)/Makefile"; \
+         echo " *"; \
+         echo " */"; \
+         echo ""; \
+         sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
+         echo ""; \
+         echo "#endif" )
+endef
+
 $(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
        $(call filechk,umlconfig)
 
index 99d3ad4a03e5ab5cd060390cc340b0fdf7f6faa4..e8ff0d8fa61037360dd3cd3488b4cab1588f0b52 100644 (file)
@@ -13,7 +13,17 @@ extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
 extern int is_remapped(void *virt);
 extern int physmem_remove_mapping(void *virt);
 extern void physmem_forget_descriptor(int fd);
-extern unsigned long to_phys(void *virt);
+
+extern unsigned long uml_physmem;
+static inline unsigned long to_phys(void *virt)
+{
+       return(((unsigned long) virt) - uml_physmem);
+}
+
+static inline void *to_virt(unsigned long phys)
+{
+       return((void *) uml_physmem + phys);
+}
 
 #endif
 
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..c13a64a
--- /dev/null
@@ -0,0 +1 @@
+/* Dummy file to make kbuild happy - unused! */
index 3942a5f245de6c038b0712155273d5097f4ff815..2517ecb8bf27d07d56fc5903c0cd26052aa7617a 100644 (file)
@@ -146,37 +146,8 @@ SECTIONS
   }
   _end = .;
   PROVIDE (end = .);
-   /* Stabs debugging sections.  */
-  .stab          0 : { *(.stab) }
-  .stabstr       0 : { *(.stabstr) }
-  .stab.excl     0 : { *(.stab.excl) }
-  .stab.exclstr  0 : { *(.stab.exclstr) }
-  .stab.index    0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment       0 : { *(.comment) }
-  /* DWARF debug sections.
-     Symbols in the DWARF debugging sections are relative to the beginning
-     of the section so we begin them at 0.  */
-  /* DWARF 1 */
-  .debug          0 : { *(.debug) }
-  .line           0 : { *(.line) }
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
-  .debug_abbrev   0 : { *(.debug_abbrev) }
-  .debug_line     0 : { *(.debug_line) }
-  .debug_frame    0 : { *(.debug_frame) }
-  .debug_str      0 : { *(.debug_str) }
-  .debug_loc      0 : { *(.debug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames) }
+
+  STABS_DEBUG
+
+  DWARF_DEBUG
 }
index 32d3076dd2204206e06aed7d835dbc4659c6e47a..a97a72e516aa6f6c6b7b4e6e0e4814b6e24f3a69 100644 (file)
@@ -34,14 +34,9 @@ EXPORT_SYMBOL(host_task_size);
 EXPORT_SYMBOL(arch_validate);
 EXPORT_SYMBOL(get_kmem_end);
 
-EXPORT_SYMBOL(page_to_phys);
-EXPORT_SYMBOL(phys_to_page);
 EXPORT_SYMBOL(high_physmem);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(um_virt_to_phys);
-EXPORT_SYMBOL(__virt_to_page);
-EXPORT_SYMBOL(to_phys);
-EXPORT_SYMBOL(to_virt);
 EXPORT_SYMBOL(mode_tt);
 EXPORT_SYMBOL(handle_page_fault);
 EXPORT_SYMBOL(find_iomem);
index a24e3b7f4bf076a7e3e1dd48d6e0ffdc906f7a6c..ea670fcc8af5b3c52b020afe31fbd09f02df97cd 100644 (file)
@@ -248,16 +248,6 @@ unsigned long high_physmem;
 
 extern unsigned long physmem_size;
 
-void *to_virt(unsigned long phys)
-{
-       return((void *) uml_physmem + phys);
-}
-
-unsigned long to_phys(void *virt)
-{
-       return(((unsigned long) virt) - uml_physmem);
-}
-
 int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
 {
        struct page *p, *map;
@@ -298,31 +288,6 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
        return(0);
 }
 
-struct page *phys_to_page(const unsigned long phys)
-{
-       return(&mem_map[phys >> PAGE_SHIFT]);
-}
-
-struct page *__virt_to_page(const unsigned long virt)
-{
-       return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
-}
-
-phys_t page_to_phys(struct page *page)
-{
-       return((page - mem_map) << PAGE_SHIFT);
-}
-
-pte_t mk_pte(struct page *page, pgprot_t pgprot)
-{
-       pte_t pte;
-
-       pte_set_val(pte, page_to_phys(page), pgprot);
-       if(pte_present(pte))
-               pte_mknewprot(pte_mknewpage(pte));
-       return(pte);
-}
-
 /* Changed during early boot */
 static unsigned long kmem_top = 0;
 
index b5fc89fe9eab8f2e51859e5a44c5f2bf5d226ab4..87cc6fd76cedecd10ac110db2b2f60cd0b109fcc 100644 (file)
@@ -57,7 +57,8 @@ good_area:
        if(is_write && !(vma->vm_flags & VM_WRITE)) 
                goto out;
 
-        if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+       /* Don't require VM_READ|VM_EXEC for write faults! */
+        if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
                 goto out;
 
        do {
@@ -84,8 +85,7 @@ survive:
                pte = pte_offset_kernel(pmd, address);
        } while(!pte_present(*pte));
        err = 0;
-       *pte = pte_mkyoung(*pte);
-       if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
+       WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte)));
        flush_tlb_page(vma, address);
 out:
        up_read(&mm->mmap_sem);
index b03326d391c9228e200b1d2c9572bbcd7f1be705..af11915ce0a8ca5155dad601c853b138f250277a 100644 (file)
@@ -93,14 +93,10 @@ SECTIONS
    *(.bss)
    *(COMMON)
   }
-  _end = . ;
+  _end = .;
   PROVIDE (end = .);
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
+
+  STABS_DEBUG
+
+  DWARF_DEBUG
 }
index bf38ca0ad78116eb0246053d51a6352bdb673cba..8be9aacb20a72f9b7c92ff6097c2db60e04372b9 100644 (file)
@@ -51,16 +51,4 @@ root_fs_image_force: $(ROOT_FS_IMAGE)
        $(OBJCOPY) $(OBJCOPY_FLAGS_BLOB) --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o
 endif
 
-
-prepare: include/asm-$(ARCH)/asm-consts.h
-
-# Generate constants from C code for use by asm files
-arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/asm-consts.h: arch/$(ARCH)/kernel/asm-consts.s
-       $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h \
-              arch/$(ARCH)/kernel/asm-consts.s \
-              root_fs_image.o
+CLEAN_FILES += root_fs_image.o
diff --git a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c
deleted file mode 100644 (file)
index 24f2913..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/hardirq.h>
-#include <asm/irq.h>
-#include <asm/errno.h>
-
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
-int main (void)
-{
-       /* offsets into the task struct */
-       DEFINE (TASK_STATE, offsetof (struct task_struct, state));
-       DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags));
-       DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
-       DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
-       DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
-       DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
-       DEFINE (TASK_MM, offsetof (struct task_struct, mm));
-       DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
-       DEFINE (TASK_PID, offsetof (struct task_struct, pid));
-
-       /* offsets into the kernel_stat struct */
-       DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs));
-
-
-       /* signal defines */
-       DEFINE (SIGSEGV, SIGSEGV);
-       DEFINE (SEGV_MAPERR, SEGV_MAPERR);
-       DEFINE (SIGTRAP, SIGTRAP);
-       DEFINE (SIGCHLD, SIGCHLD);
-       DEFINE (SIGILL, SIGILL);
-       DEFINE (TRAP_TRACE, TRAP_TRACE);
-
-       /* ptrace flag bits */
-       DEFINE (PT_PTRACED, PT_PTRACED);
-       DEFINE (PT_DTRACE, PT_DTRACE);
-
-       /* error values */
-       DEFINE (ENOSYS, ENOSYS);
-
-       /* clone flag bits */
-       DEFINE (CLONE_VFORK, CLONE_VFORK);
-       DEFINE (CLONE_VM, CLONE_VM);
-
-       return 0;
-}
diff --git a/arch/v850/kernel/asm-offsets.c b/arch/v850/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..24f2913
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <asm/irq.h>
+#include <asm/errno.h>
+
+#define DEFINE(sym, val) \
+       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main (void)
+{
+       /* offsets into the task struct */
+       DEFINE (TASK_STATE, offsetof (struct task_struct, state));
+       DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags));
+       DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace));
+       DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked));
+       DEFINE (TASK_THREAD, offsetof (struct task_struct, thread));
+       DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+       DEFINE (TASK_MM, offsetof (struct task_struct, mm));
+       DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
+       DEFINE (TASK_PID, offsetof (struct task_struct, pid));
+
+       /* offsets into the kernel_stat struct */
+       DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs));
+
+
+       /* signal defines */
+       DEFINE (SIGSEGV, SIGSEGV);
+       DEFINE (SEGV_MAPERR, SEGV_MAPERR);
+       DEFINE (SIGTRAP, SIGTRAP);
+       DEFINE (SIGCHLD, SIGCHLD);
+       DEFINE (SIGILL, SIGILL);
+       DEFINE (TRAP_TRACE, TRAP_TRACE);
+
+       /* ptrace flag bits */
+       DEFINE (PT_PTRACED, PT_PTRACED);
+       DEFINE (PT_DTRACE, PT_DTRACE);
+
+       /* error values */
+       DEFINE (ENOSYS, ENOSYS);
+
+       /* clone flag bits */
+       DEFINE (CLONE_VFORK, CLONE_VFORK);
+       DEFINE (CLONE_VM, CLONE_VM);
+
+       return 0;
+}
index 895e27b1d839f795491fa84a6464e5e929b1f373..d991e4547dbb6ab684b6af361f575e6d142e4bd0 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/irq.h>
 #include <asm/errno.h>
 
-#include <asm/asm-consts.h>
+#include <asm/asm-offsets.h>
 
 
 /* Make a slightly more convenient alias for C_SYMBOL_NAME.  */
index 336cbf21dc8ffa8ba8791766c3d55bb9b0c84aeb..9e85969ba9767d714486334c0b31f743470b5cb2 100644 (file)
@@ -67,13 +67,13 @@ static void ack_none(unsigned int irq)
 #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
+       .typename = "none",
+       .startup = startup_none,
+       .shutdown = shutdown_none,
+       .enable = enable_none,
+       .disable = disable_none,
+       .ack = ack_none,
+       .end = end_none
 };
 
 volatile unsigned long irq_err_count, spurious_count;
index abd48409dcca51f5d4816aaf54e4fa9e149e7fe9..62bdb8d29fc05191750c7f1033a802e24f445d4d 100644 (file)
@@ -138,13 +138,13 @@ static void nmi_end (unsigned irq)
 }
 
 static struct hw_interrupt_type nmi_irq_type = {
-       "NMI",
-       irq_zero,               /* startup */
-       irq_nop,                /* shutdown */
-       irq_nop,                /* enable */
-       irq_nop,                /* disable */
-       irq_nop,                /* ack */
-       nmi_end,                /* end */
+       .typename = "NMI",
+       .startup = irq_zero,            /* startup */
+       .shutdown = irq_nop,            /* shutdown */
+       .enable = irq_nop,              /* enable */
+       .disable = irq_nop,             /* disable */
+       .ack = irq_nop,         /* ack */
+       .end = nmi_end,         /* end */
 };
 
 void __init init_IRQ (void)
index e2cc5580fa2a1eb9191962261857388698dbbf06..17049aaa8f11832cf4a431e9a9e4a09282dd2208 100644 (file)
@@ -73,13 +73,13 @@ static void irq_nop (unsigned irq) { }
 static unsigned irq_zero (unsigned irq) { return 0; }
 
 static struct hw_interrupt_type sim_irq_type = {
-       "IRQ",
-       irq_zero,               /* startup */
-       irq_nop,                /* shutdown */
-       irq_nop,                /* enable */
-       irq_nop,                /* disable */
-       irq_nop,                /* ack */
-       irq_nop,                /* end */
+       .typename = "IRQ",
+       .startup = irq_zero,            /* startup */
+       .shutdown = irq_nop,            /* shutdown */
+       .enable = irq_nop,              /* enable */
+       .disable = irq_nop,             /* disable */
+       .ack = irq_nop,         /* ack */
+       .end = irq_nop,         /* end */
 };
 
 void __init mach_init_irqs (void)
index 4c6ed96d5f7c52356ecdb73aaafefe2ced07fce3..a9cd42e61828d8860c41c06b71ed58e1dfb6956f 100644 (file)
@@ -86,16 +86,6 @@ install fdimage fdimage144 fdimage288: vmlinux
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-prepare: include/asm-$(ARCH)/offset.h
-
-arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
-                                  include/config/MARKER
-
-include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += include/asm-$(ARCH)/offset.h
-
 define archhelp
   echo  '* bzImage     - Compressed kernel image (arch/$(ARCH)/boot/bzImage)'
   echo  '  install     - Install kernel using'
index f4399c701b77957d01d93fa7ada889bd6d47e443..18c6e915d69b84260a43b979b28e5058c60a193a 100644 (file)
@@ -46,7 +46,7 @@ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
 $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
                              $(obj)/vmlinux.bin $(obj)/tools/build FORCE
        $(call if_changed,image)
-       @echo 'Kernel: $@ is ready'
+       @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
index b38d5b8b5fb844ebf92ed2221faa1bcf2d274e6a..0e10fd84c7cc79e2ee31832e6104c915f3c50597 100644 (file)
@@ -83,7 +83,7 @@ static unsigned char *real_mode; /* Pointer to real-mode data */
 #endif
 #define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
 
-extern char input_data[];
+extern unsigned char input_data[];
 extern int input_len;
 
 static long bytes_out = 0;
@@ -288,7 +288,7 @@ void setup_normal_output_buffer(void)
 #else
        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
 #endif
-       output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
+       output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
        free_mem_end_ptr = (long)real_mode;
 }
 
@@ -305,7 +305,7 @@ void setup_output_buffer_if_we_run_high(struct moveparams *mv)
 #else
        if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
 #endif 
-       mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+       mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
        low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
          ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
        low_buffer_size = low_buffer_end - LOW_BUFFER_START;
index bf57e2362bf4cbd79bc9f5e02d7f11b8b18abc0b..f8db7e500fbfdd727e16ac7a9c71f1cab078f243 100644 (file)
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc6-git3
-# Fri Aug 12 16:40:34 2005
+# Linux kernel version: 2.6.13-git11
+# Mon Sep 12 16:16:16 2005
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
 CONFIG_X86=y
+CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -13,6 +14,7 @@ CONFIG_X86_CMPXCHG=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -37,6 +40,7 @@ CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
@@ -102,6 +106,7 @@ CONFIG_DISCONTIGMEM_MANUAL=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_NR_CPUS=32
@@ -122,6 +127,7 @@ CONFIG_HZ=250
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ISA_DMA_API=y
+CONFIG_GENERIC_PENDING_IRQ=y
 
 #
 # Power management options
@@ -194,7 +200,6 @@ CONFIG_UNORDERED_IO=y
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -234,7 +239,10 @@ CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# 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
@@ -244,8 +252,8 @@ CONFIG_IP_FIB_HASH=y
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-CONFIG_IP_TCPDIAG_IPV6=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 CONFIG_IPV6=y
@@ -257,6 +265,11 @@ CONFIG_IPV6=y
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
@@ -280,9 +293,11 @@ CONFIG_IPV6=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETFILTER_NETLINK is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -329,7 +344,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
 CONFIG_LBD=y
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -409,6 +423,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -432,7 +447,7 @@ CONFIG_BLK_DEV_SD=y
 #
 # SCSI Transport Attributes
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 
@@ -458,6 +473,7 @@ CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_AHCI is not set
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
@@ -536,6 +552,11 @@ CONFIG_TUN=y
 #
 # CONFIG_ARCNET is not set
 
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -586,6 +607,7 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
@@ -595,6 +617,7 @@ CONFIG_TIGON3=y
 #
 # Ethernet (10000 Mbit)
 #
+# CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
@@ -749,7 +772,6 @@ CONFIG_MAX_RAW_DEVS=256
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
 
 #
 # Dallas's 1-wire bus
@@ -760,6 +782,7 @@ CONFIG_MAX_RAW_DEVS=256
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -767,6 +790,10 @@ CONFIG_HWMON=y
 #
 # CONFIG_IBM_ASM is not set
 
+#
+# Multimedia Capabilities Port drivers
+#
+
 #
 # Multimedia devices
 #
@@ -858,9 +885,8 @@ CONFIG_USB_UHCI_HCD=y
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
 # CONFIG_USB_ACM is not set
 CONFIG_USB_PRINTER=y
 
@@ -877,6 +903,7 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
 
 #
 # USB Input Devices
@@ -893,6 +920,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_MTOUCH is not set
 # CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
@@ -976,6 +1004,8 @@ CONFIG_USB_MON=y
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
+# CONFIG_DELL_RBU is not set
+CONFIG_DCDBAS=m
 
 #
 # File systems
@@ -1000,10 +1030,6 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 # CONFIG_REISERFS_FS_SECURITY is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -1012,6 +1038,7 @@ CONFIG_INOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -1037,12 +1064,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -1074,6 +1100,7 @@ CONFIG_NFSD_V3=y
 # CONFIG_NFSD_V3_ACL is not set
 # CONFIG_NFSD_V4 is not set
 CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
@@ -1086,6 +1113,7 @@ CONFIG_SUNRPC=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -1150,6 +1178,7 @@ CONFIG_OPROFILE=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1157,6 +1186,7 @@ CONFIG_LOG_BUF_SHIFT=18
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
+# CONFIG_FRAME_POINTER is not set
 CONFIG_INIT_DEBUG=y
 # CONFIG_IOMMU_DEBUG is not set
 CONFIG_KPROBES=y
@@ -1180,5 +1210,6 @@ CONFIG_KPROBES=y
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
index d259f8a6f811d7761a5bc6d850e7c137da576075..419758f19ca4f4ec4da887da494b89f397f149c7 100644 (file)
 static int tiocgdev(unsigned fd, unsigned cmd,  unsigned int __user *ptr) 
 { 
 
-       struct file *file = fget(fd);
+       struct file *file;
        struct tty_struct *real_tty;
+       int fput_needed, ret;
 
+       file = fget_light(fd, &fput_needed);
        if (!file)
                return -EBADF;
+
+       ret = -EINVAL;
        if (file->f_op->ioctl != tty_ioctl)
-               return -EINVAL; 
+               goto out;
        real_tty = (struct tty_struct *)file->private_data;
        if (!real_tty)  
-               return -EINVAL; 
-       return put_user(new_encode_dev(tty_devnum(real_tty)), ptr); 
+               goto out;
+
+       ret = put_user(new_encode_dev(tty_devnum(real_tty)), ptr); 
+
+out:
+       fput_light(file, fput_needed);
+       return ret;
 } 
 
 #define RTC_IRQP_READ32        _IOR('p', 0x0b, unsigned int)    /* Read IRQ rate   */
index f174083d55672335bdbc0a442ae5c8fc4c2a697e..e0eb0c712fe91fbddfc74beb9048eace392e1566 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <asm/dwarf2.h>
 #include <asm/calling.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/current.h>
 #include <asm/errno.h>
 #include <asm/ia32_unistd.h>   
  * with the int 0x80 path.
  */    
 ENTRY(ia32_sysenter_target)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,0
+       CFI_REGISTER    rsp,rbp
        swapgs
        movq    %gs:pda_kernelstack, %rsp
        addq    $(PDA_STACKOFFSET),%rsp 
        sti     
        movl    %ebp,%ebp               /* zero extension */
        pushq   $__USER32_DS
+       CFI_ADJUST_CFA_OFFSET 8
+       /*CFI_REL_OFFSET ss,0*/
        pushq   %rbp
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rsp,0
        pushfq
+       CFI_ADJUST_CFA_OFFSET 8
+       /*CFI_REL_OFFSET rflags,0*/
        movl    $VSYSCALL32_SYSEXIT, %r10d
+       CFI_REGISTER rip,r10
        pushq   $__USER32_CS
+       CFI_ADJUST_CFA_OFFSET 8
+       /*CFI_REL_OFFSET cs,0*/
        movl    %eax, %eax
        pushq   %r10
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rip,0
        pushq   %rax
+       CFI_ADJUST_CFA_OFFSET 8
        cld
        SAVE_ARGS 0,0,1
        /* no need to do an access_ok check here because rbp has been
@@ -79,6 +93,7 @@ ENTRY(ia32_sysenter_target)
        .previous       
        GET_THREAD_INFO(%r10)
        testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+       CFI_REMEMBER_STATE
        jnz  sysenter_tracesys
 sysenter_do_call:      
        cmpl    $(IA32_NR_syscalls),%eax
@@ -94,14 +109,20 @@ sysenter_do_call:
        andl  $~0x200,EFLAGS-R11(%rsp) 
        RESTORE_ARGS 1,24,1,1,1,1
        popfq
+       CFI_ADJUST_CFA_OFFSET -8
+       /*CFI_RESTORE rflags*/
        popq    %rcx                            /* User %esp */
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rsp,rcx
        movl    $VSYSCALL32_SYSEXIT,%edx        /* User %eip */
+       CFI_REGISTER rip,rdx
        swapgs
        sti             /* sti only takes effect after the next instruction */
        /* sysexit */
        .byte   0xf, 0x35
 
 sysenter_tracesys:
+       CFI_RESTORE_STATE
        SAVE_REST
        CLEAR_RREGS
        movq    $-ENOSYS,RAX(%rsp)      /* really needed? */
@@ -140,21 +161,28 @@ sysenter_tracesys:
  * with the int 0x80 path.     
  */    
 ENTRY(ia32_cstar_target)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,0
+       CFI_REGISTER    rip,rcx
+       /*CFI_REGISTER  rflags,r11*/
        swapgs
        movl    %esp,%r8d
+       CFI_REGISTER    rsp,r8
        movq    %gs:pda_kernelstack,%rsp
        sti
        SAVE_ARGS 8,1,1
        movl    %eax,%eax       /* zero extension */
        movq    %rax,ORIG_RAX-ARGOFFSET(%rsp)
        movq    %rcx,RIP-ARGOFFSET(%rsp)
+       CFI_REL_OFFSET rip,RIP-ARGOFFSET
        movq    %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
        movl    %ebp,%ecx
        movq    $__USER32_CS,CS-ARGOFFSET(%rsp)
        movq    $__USER32_DS,SS-ARGOFFSET(%rsp)
        movq    %r11,EFLAGS-ARGOFFSET(%rsp)
+       /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
        movq    %r8,RSP-ARGOFFSET(%rsp) 
+       CFI_REL_OFFSET rsp,RSP-ARGOFFSET
        /* no need to do an access_ok check here because r8 has been
           32bit zero extended */ 
        /* hardware stack frame is complete now */      
@@ -164,6 +192,7 @@ ENTRY(ia32_cstar_target)
        .previous       
        GET_THREAD_INFO(%r10)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
+       CFI_REMEMBER_STATE
        jnz   cstar_tracesys
 cstar_do_call: 
        cmpl $IA32_NR_syscalls,%eax
@@ -177,12 +206,16 @@ cstar_do_call:
        jnz  int_ret_from_sys_call
        RESTORE_ARGS 1,-ARG_SKIP,1,1,1
        movl RIP-ARGOFFSET(%rsp),%ecx
+       CFI_REGISTER rip,rcx
        movl EFLAGS-ARGOFFSET(%rsp),%r11d       
+       /*CFI_REGISTER rflags,r11*/
        movl RSP-ARGOFFSET(%rsp),%esp
+       CFI_RESTORE rsp
        swapgs
        sysretl
        
 cstar_tracesys:        
+       CFI_RESTORE_STATE
        SAVE_REST
        CLEAR_RREGS
        movq $-ENOSYS,RAX(%rsp) /* really needed? */
@@ -226,11 +259,18 @@ ia32_badarg:
  */                            
 
 ENTRY(ia32_syscall)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,SS+8-RIP
+       /*CFI_REL_OFFSET        ss,SS-RIP*/
+       CFI_REL_OFFSET  rsp,RSP-RIP
+       /*CFI_REL_OFFSET        rflags,EFLAGS-RIP*/
+       /*CFI_REL_OFFSET        cs,CS-RIP*/
+       CFI_REL_OFFSET  rip,RIP-RIP
        swapgs  
        sti
        movl %eax,%eax
        pushq %rax
+       CFI_ADJUST_CFA_OFFSET 8
        cld
        /* note the registers are not zero extended to the sf.
           this could be a problem. */
@@ -278,6 +318,8 @@ quiet_ni_syscall:
        jmp  ia32_ptregs_common 
        .endm
 
+       CFI_STARTPROC
+
        PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
        PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
        PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
@@ -290,8 +332,9 @@ quiet_ni_syscall:
        PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
 
 ENTRY(ia32_ptregs_common)
-       CFI_STARTPROC
        popq %r11
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rip, r11
        SAVE_REST
        call *%rax
        RESTORE_REST
index 04d80406ce4fed4c1a6ce646253675c65b074269..5389df610e78277d0a6329f98a16d3f1f52c27d0 100644 (file)
@@ -751,7 +751,7 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
        set_fs(old_fs);
        
-       if (!ret && offset && put_user(of, offset))
+       if (offset && put_user(of, offset))
                return -EFAULT;
                
        return ret;
index e2aaf3de8a4282a0fce239ec07b371b864a8487f..b024965bb689f55705c72770a0cec9cb632ea896 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 #include <asm/ia32_unistd.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/segment.h>
 
        .text
index 8fb8e0ff3afa73a2e08f6d8c41370c10ee94e7ec..71f3de586b5668a9b50ef10e05077c82438c5c55 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 #include <asm/ia32_unistd.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 
        .text
        .section .text.vsyscall,"ax"
index 1579bdd0adcde450ad0a4991e1b6986895800822..bcdd0a805fe70c7357b0aab2adefa59ab081d31e 100644 (file)
@@ -46,3 +46,4 @@ microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
 intel_cacheinfo-y              += ../../i386/kernel/cpu/intel_cacheinfo.o
 quirks-y                       += ../../i386/kernel/quirks.o
 i8237-y                                += ../../i386/kernel/i8237.o
+msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
index 148f6f7ea315889f1bf0d0d64d92b6b44db7bad2..867a0ebee1773c2a1a678245a665abc8dfbe1df8 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/bootmem.h>
-#include <linux/irq.h>
 #include <linux/acpi.h>
 #include <asm/mpspec.h>
 #include <asm/io.h>
index c9a6b812e926cf3f5c79493433cda35b5c9c7e3b..962ad4823b6a567d4f340bca8d101a2e958dfbd2 100644 (file)
@@ -245,6 +245,8 @@ void __init iommu_hole_init(void)
                
        if (aper_alloc) { 
                /* Got the aperture from the AGP bridge */
+       } else if (swiotlb && !valid_agp) {
+               /* Do nothing */
        } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
                   force_iommu ||
                   valid_agp ||
index 375d369570ca3dbbb365b363585d5b6ecff1ef57..b6e7715d877f38a0d191616c22dc7f9fe98e4509 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
@@ -109,11 +108,8 @@ void clear_local_APIC(void)
        if (maxlvt >= 4)
                apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
        v = GET_APIC_VERSION(apic_read(APIC_LVR));
-       if (APIC_INTEGRATED(v)) {       /* !82489DX */
-               if (maxlvt > 3)         /* Due to Pentium errata 3AP and 11AP. */
-                       apic_write(APIC_ESR, 0);
-               apic_read(APIC_ESR);
-       }
+       apic_write(APIC_ESR, 0);
+       apic_read(APIC_ESR);
 }
 
 void __init connect_bsp_APIC(void)
@@ -316,8 +312,6 @@ void __init init_bsp_APIC(void)
         */
        apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
        value = APIC_DM_NMI;
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
-               value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write_around(APIC_LVT1, value);
 }
 
@@ -325,14 +319,6 @@ void __cpuinit setup_local_APIC (void)
 {
        unsigned int value, ver, maxlvt;
 
-       /* Pound the ESR really hard over the head with a big hammer - mbligh */
-       if (esr_disable) {
-               apic_write(APIC_ESR, 0);
-               apic_write(APIC_ESR, 0);
-               apic_write(APIC_ESR, 0);
-               apic_write(APIC_ESR, 0);
-       }
-
        value = apic_read(APIC_LVR);
        ver = GET_APIC_VERSION(value);
 
@@ -430,15 +416,11 @@ void __cpuinit setup_local_APIC (void)
                value = APIC_DM_NMI;
        else
                value = APIC_DM_NMI | APIC_LVT_MASKED;
-       if (!APIC_INTEGRATED(ver))              /* 82489DX */
-               value |= APIC_LVT_LEVEL_TRIGGER;
        apic_write_around(APIC_LVT1, value);
 
-       if (APIC_INTEGRATED(ver) && !esr_disable) {             /* !82489DX */
+       {
                unsigned oldvalue;
                maxlvt = get_maxlvt();
-               if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
-                       apic_write(APIC_ESR, 0);
                oldvalue = apic_read(APIC_ESR);
                value = ERROR_APIC_VECTOR;      // enables sending errors
                apic_write_around(APIC_LVTERR, value);
@@ -452,17 +434,6 @@ void __cpuinit setup_local_APIC (void)
                        apic_printk(APIC_VERBOSE,
                        "ESR value after enabling vector: %08x, after %08x\n",
                        oldvalue, value);
-       } else {
-               if (esr_disable)        
-                       /* 
-                        * Something untraceble is creating bad interrupts on 
-                        * secondary quads ... for the moment, just leave the
-                        * ESR disabled - we can't do anything useful with the
-                        * errors anyway - mbligh
-                        */
-                       apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
-               else 
-                       apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
        }
 
        nmi_watchdog_default();
@@ -650,8 +621,7 @@ void __init init_apic_mappings(void)
         * Fetch the APIC ID of the BSP in case we have a
         * default configuration (or the MP table is broken).
         */
-       if (boot_cpu_id == -1U)
-               boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
+       boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
 
 #ifdef CONFIG_X86_IO_APIC
        {
@@ -693,8 +663,6 @@ static void __setup_APIC_LVTT(unsigned int clocks)
 
        ver = GET_APIC_VERSION(apic_read(APIC_LVR));
        lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
-       if (!APIC_INTEGRATED(ver))
-               lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
        apic_write_around(APIC_LVTT, lvtt_value);
 
        /*
@@ -1081,7 +1049,7 @@ int __init APIC_init_uniprocessor (void)
 
        connect_bsp_APIC();
 
-       phys_cpu_present_map = physid_mask_of_physid(0);
+       phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
        apic_write_around(APIC_ID, boot_cpu_id);
 
        setup_local_APIC();
index 35b4c3fcbb37ff95dbd556b87da576db49cfe3ba..aaa6d383351798dca10eb8f7402a5c90a0ac1f95 100644 (file)
@@ -39,7 +39,6 @@ int main(void)
        ENTRY(kernelstack); 
        ENTRY(oldrsp); 
        ENTRY(pcurrent); 
-       ENTRY(irqrsp);
        ENTRY(irqcount);
        ENTRY(cpunumber);
        ENTRY(irqstackptr);
index d7fa4248501cc300ad4470fc38820b16a6a57c8c..535e04466079857a09d3f9b0c6649f15f36301e6 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
-#include <linux/irq.h>
 #include <linux/reboot.h>
 #include <linux/kexec.h>
 
index 116ac5f53dced70d0098178e57b7e09207d90603..eb7929eea7b33c4743b533a0d39bf8c22c42707c 100644 (file)
@@ -131,7 +131,7 @@ void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned lon
 
                if (ei->type != E820_RAM || 
                    ei->addr+ei->size <= start || 
-                   ei->addr > end)
+                   ei->addr >= end)
                        continue;
 
                addr = round_up(ei->addr, PAGE_SIZE);
@@ -567,7 +567,7 @@ unsigned long pci_mem_start = 0xaeedbabe;
  */
 __init void e820_setup_gap(void)
 {
-       unsigned long gapstart, gapsize;
+       unsigned long gapstart, gapsize, round;
        unsigned long last;
        int i;
        int found = 0;
@@ -604,14 +604,14 @@ __init void e820_setup_gap(void)
        }
 
        /*
-        * Start allocating dynamic PCI memory a bit into the gap,
-        * aligned up to the nearest megabyte.
-        *
-        * Question: should we try to pad it up a bit (do something
-        * like " + (gapsize >> 3)" in there too?). We now have the
-        * technology.
+        * See how much we want to round up: start off with
+        * rounding to the next 1MB area.
         */
-       pci_mem_start = (gapstart + 0xfffff) & ~0xfffff;
+       round = 0x100000;
+       while ((gapsize >> 4) > round)
+               round += round;
+       /* Fun with two's complement */
+       pci_mem_start = (gapstart + round) & -round;
 
        printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
                pci_mem_start, gapstart, gapsize);
index 9631c747c5e3750580cf06dea4b0e8e1324a757f..9cd968dd0f5a4bd3b9d4b83525f94ee5386fec14 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/processor.h>
+#include <asm/fcntl.h>
 
 /* Simple VGA output */
 
@@ -158,6 +159,47 @@ static struct console early_serial_console = {
        .index =        -1,
 };
 
+/* Console interface to a host file on AMD's SimNow! */
+
+static int simnow_fd;
+
+enum {
+       MAGIC1 = 0xBACCD00A,
+       MAGIC2 = 0xCA110000,
+       XOPEN = 5,
+       XWRITE = 4,
+};
+
+static noinline long simnow(long cmd, long a, long b, long c)
+{
+       long ret;
+       asm volatile("cpuid" :
+                    "=a" (ret) :
+                    "b" (a), "c" (b), "d" (c), "0" (MAGIC1), "D" (cmd + MAGIC2));
+       return ret;
+}
+
+void __init simnow_init(char *str)
+{
+       char *fn = "klog";
+       if (*str == '=')
+               fn = ++str;
+       /* error ignored */
+       simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
+}
+
+static void simnow_write(struct console *con, const char *s, unsigned n)
+{
+       simnow(XWRITE, simnow_fd, (unsigned long)s, n);
+}
+
+static struct console simnow_console = {
+       .name =         "simnow",
+       .write =        simnow_write,
+       .flags =        CON_PRINTBUFFER,
+       .index =        -1,
+};
+
 /* Direct interface for emergencies */
 struct console *early_console = &early_vga_console;
 static int early_console_initialized = 0;
@@ -205,6 +247,10 @@ int __init setup_early_printk(char *opt)
                max_xpos = SCREEN_INFO.orig_video_cols;
                max_ypos = SCREEN_INFO.orig_video_lines;
                early_console = &early_vga_console; 
+       } else if (!strncmp(buf, "simnow", 6)) {
+               simnow_init(buf + 6);
+               early_console = &simnow_console;
+               keep_early = 1;
        }
        early_console_initialized = 1;
        register_console(early_console);       
index be51dbe1f75ec1a91765e8a4735a052ae144c6e1..7937971d1853bd5187cfe615e24c4a5cf35689be 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/errno.h>
 #include <asm/dwarf2.h>
 #include <asm/calling.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/msr.h>
 #include <asm/unistd.h>
 #include <asm/thread_info.h>
        xorl %eax, %eax
        pushq %rax /* ss */
        CFI_ADJUST_CFA_OFFSET   8
+       /*CFI_REL_OFFSET        ss,0*/
        pushq %rax /* rsp */
        CFI_ADJUST_CFA_OFFSET   8
-       CFI_OFFSET      rip,0
+       CFI_REL_OFFSET  rsp,0
        pushq $(1<<9) /* eflags - interrupts on */
        CFI_ADJUST_CFA_OFFSET   8
+       /*CFI_REL_OFFSET        rflags,0*/
        pushq $__KERNEL_CS /* cs */
        CFI_ADJUST_CFA_OFFSET   8
+       /*CFI_REL_OFFSET        cs,0*/
        pushq \child_rip /* rip */
        CFI_ADJUST_CFA_OFFSET   8
-       CFI_OFFSET      rip,0
+       CFI_REL_OFFSET  rip,0
        pushq   %rax /* orig rax */
        CFI_ADJUST_CFA_OFFSET   8
        .endm
        CFI_ADJUST_CFA_OFFSET   -(6*8)
        .endm
 
-       .macro  CFI_DEFAULT_STACK
-       CFI_ADJUST_CFA_OFFSET  (SS)
-       CFI_OFFSET      r15,R15-SS
-       CFI_OFFSET      r14,R14-SS
-       CFI_OFFSET      r13,R13-SS
-       CFI_OFFSET      r12,R12-SS
-       CFI_OFFSET      rbp,RBP-SS
-       CFI_OFFSET      rbx,RBX-SS
-       CFI_OFFSET      r11,R11-SS
-       CFI_OFFSET      r10,R10-SS
-       CFI_OFFSET      r9,R9-SS
-       CFI_OFFSET      r8,R8-SS
-       CFI_OFFSET      rax,RAX-SS
-       CFI_OFFSET      rcx,RCX-SS
-       CFI_OFFSET      rdx,RDX-SS
-       CFI_OFFSET      rsi,RSI-SS
-       CFI_OFFSET      rdi,RDI-SS
-       CFI_OFFSET      rsp,RSP-SS
-       CFI_OFFSET      rip,RIP-SS
+       .macro  CFI_DEFAULT_STACK start=1
+       .if \start
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,SS+8
+       .else
+       CFI_DEF_CFA_OFFSET SS+8
+       .endif
+       CFI_REL_OFFSET  r15,R15
+       CFI_REL_OFFSET  r14,R14
+       CFI_REL_OFFSET  r13,R13
+       CFI_REL_OFFSET  r12,R12
+       CFI_REL_OFFSET  rbp,RBP
+       CFI_REL_OFFSET  rbx,RBX
+       CFI_REL_OFFSET  r11,R11
+       CFI_REL_OFFSET  r10,R10
+       CFI_REL_OFFSET  r9,R9
+       CFI_REL_OFFSET  r8,R8
+       CFI_REL_OFFSET  rax,RAX
+       CFI_REL_OFFSET  rcx,RCX
+       CFI_REL_OFFSET  rdx,RDX
+       CFI_REL_OFFSET  rsi,RSI
+       CFI_REL_OFFSET  rdi,RDI
+       CFI_REL_OFFSET  rip,RIP
+       /*CFI_REL_OFFSET        cs,CS*/
+       /*CFI_REL_OFFSET        rflags,EFLAGS*/
+       CFI_REL_OFFSET  rsp,RSP
+       /*CFI_REL_OFFSET        ss,SS*/
        .endm
 /*
  * A newly forked process directly context switches into this.
  */    
 /* rdi:        prev */ 
 ENTRY(ret_from_fork)
-       CFI_STARTPROC
        CFI_DEFAULT_STACK
        call schedule_tail
        GET_THREAD_INFO(%rcx)
@@ -172,16 +182,21 @@ rff_trace:
  */                                    
 
 ENTRY(system_call)
-       CFI_STARTPROC
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,0
+       CFI_REGISTER    rip,rcx
+       /*CFI_REGISTER  rflags,r11*/
        swapgs
        movq    %rsp,%gs:pda_oldrsp 
        movq    %gs:pda_kernelstack,%rsp
        sti                                     
        SAVE_ARGS 8,1
        movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
-       movq  %rcx,RIP-ARGOFFSET(%rsp)  
+       movq  %rcx,RIP-ARGOFFSET(%rsp)
+       CFI_REL_OFFSET rip,RIP-ARGOFFSET
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
+       CFI_REMEMBER_STATE
        jnz tracesys
        cmpq $__NR_syscall_max,%rax
        ja badsys
@@ -201,9 +216,12 @@ sysret_check:
        cli
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
+       CFI_REMEMBER_STATE
        jnz  sysret_careful 
        movq RIP-ARGOFFSET(%rsp),%rcx
+       CFI_REGISTER    rip,rcx
        RESTORE_ARGS 0,-ARG_SKIP,1
+       /*CFI_REGISTER  rflags,r11*/
        movq    %gs:pda_oldrsp,%rsp
        swapgs
        sysretq
@@ -211,12 +229,15 @@ sysret_check:
        /* Handle reschedules */
        /* edx: work, edi: workmask */  
 sysret_careful:
+       CFI_RESTORE_STATE
        bt $TIF_NEED_RESCHED,%edx
        jnc sysret_signal
        sti
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET 8
        call schedule
        popq  %rdi
+       CFI_ADJUST_CFA_OFFSET -8
        jmp sysret_check
 
        /* Handle a signal */ 
@@ -234,8 +255,13 @@ sysret_signal:
 1:     movl $_TIF_NEED_RESCHED,%edi
        jmp sysret_check
        
+badsys:
+       movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
+       jmp ret_from_sys_call
+
        /* Do syscall tracing */
 tracesys:                       
+       CFI_RESTORE_STATE
        SAVE_REST
        movq $-ENOSYS,RAX(%rsp)
        FIXUP_TOP_OF_STACK %rdi
@@ -254,16 +280,29 @@ tracesys:
        RESTORE_TOP_OF_STACK %rbx
        RESTORE_REST
        jmp ret_from_sys_call
+       CFI_ENDPROC
                
-badsys:
-       movq $-ENOSYS,RAX-ARGOFFSET(%rsp)       
-       jmp ret_from_sys_call
-
 /* 
  * Syscall return path ending with IRET.
  * Has correct top of stack, but partial stack frame.
  */    
-ENTRY(int_ret_from_sys_call)   
+ENTRY(int_ret_from_sys_call)
+       CFI_STARTPROC   simple
+       CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
+       /*CFI_REL_OFFSET        ss,SS-ARGOFFSET*/
+       CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
+       /*CFI_REL_OFFSET        rflags,EFLAGS-ARGOFFSET*/
+       /*CFI_REL_OFFSET        cs,CS-ARGOFFSET*/
+       CFI_REL_OFFSET  rip,RIP-ARGOFFSET
+       CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
+       CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
+       CFI_REL_OFFSET  rax,RAX-ARGOFFSET
+       CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
+       CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
+       CFI_REL_OFFSET  r8,R8-ARGOFFSET
+       CFI_REL_OFFSET  r9,R9-ARGOFFSET
+       CFI_REL_OFFSET  r10,R10-ARGOFFSET
+       CFI_REL_OFFSET  r11,R11-ARGOFFSET
        cli
        testl $3,CS-ARGOFFSET(%rsp)
        je retint_restore_args
@@ -284,8 +323,10 @@ int_careful:
        jnc  int_very_careful
        sti
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET 8
        call schedule
        popq %rdi
+       CFI_ADJUST_CFA_OFFSET -8
        cli
        jmp int_with_check
 
@@ -297,9 +338,11 @@ int_very_careful:
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
        jz int_signal
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET 8
        leaq 8(%rsp),%rdi       # &ptregs -> arg1       
        call syscall_trace_leave
        popq %rdi
+       CFI_ADJUST_CFA_OFFSET -8
        andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
        cli
        jmp int_restore_rest
@@ -329,6 +372,8 @@ int_restore_rest:
        jmp     ptregscall_common
        .endm
 
+       CFI_STARTPROC
+
        PTREGSCALL stub_clone, sys_clone, %r8
        PTREGSCALL stub_fork, sys_fork, %rdi
        PTREGSCALL stub_vfork, sys_vfork, %rdi
@@ -337,40 +382,49 @@ int_restore_rest:
        PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
-       CFI_STARTPROC
        popq %r11
-       CFI_ADJUST_CFA_OFFSET   -8
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rip, r11
        SAVE_REST
        movq %r11, %r15
+       CFI_REGISTER rip, r15
        FIXUP_TOP_OF_STACK %r11
        call *%rax
        RESTORE_TOP_OF_STACK %r11
        movq %r15, %r11
+       CFI_REGISTER rip, r11
        RESTORE_REST
        pushq %r11
-       CFI_ADJUST_CFA_OFFSET   8
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rip, 0
        ret
        CFI_ENDPROC
        
 ENTRY(stub_execve)
        CFI_STARTPROC
        popq %r11
-       CFI_ADJUST_CFA_OFFSET   -8
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_REGISTER rip, r11
        SAVE_REST
        movq %r11, %r15
+       CFI_REGISTER rip, r15
        FIXUP_TOP_OF_STACK %r11
        call sys_execve
        GET_THREAD_INFO(%rcx)
        bt $TIF_IA32,threadinfo_flags(%rcx)
+       CFI_REMEMBER_STATE
        jc exec_32bit
        RESTORE_TOP_OF_STACK %r11
        movq %r15, %r11
+       CFI_REGISTER rip, r11
        RESTORE_REST
-       push %r11
+       pushq %r11
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rip, 0
        ret
 
 exec_32bit:
-       CFI_ADJUST_CFA_OFFSET   REST_SKIP
+       CFI_RESTORE_STATE
        movq %rax,RAX(%rsp)
        RESTORE_REST
        jmp int_ret_from_sys_call
@@ -382,7 +436,8 @@ exec_32bit:
  */                
 ENTRY(stub_rt_sigreturn)
        CFI_STARTPROC
-       addq $8, %rsp           
+       addq $8, %rsp
+       CFI_ADJUST_CFA_OFFSET   -8
        SAVE_REST
        movq %rsp,%rdi
        FIXUP_TOP_OF_STACK %r11
@@ -392,6 +447,25 @@ ENTRY(stub_rt_sigreturn)
        jmp int_ret_from_sys_call
        CFI_ENDPROC
 
+/*
+ * initial frame state for interrupts and exceptions
+ */
+       .macro _frame ref
+       CFI_STARTPROC simple
+       CFI_DEF_CFA rsp,SS+8-\ref
+       /*CFI_REL_OFFSET ss,SS-\ref*/
+       CFI_REL_OFFSET rsp,RSP-\ref
+       /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
+       /*CFI_REL_OFFSET cs,CS-\ref*/
+       CFI_REL_OFFSET rip,RIP-\ref
+       .endm
+
+/* initial frame state for interrupts (and exceptions without error code) */
+#define INTR_FRAME _frame RIP
+/* initial frame state for exceptions with error code (and interrupts with
+   vector already pushed) */
+#define XCPT_FRAME _frame ORIG_RAX
+
 /* 
  * Interrupt entry/exit.
  *
@@ -402,10 +476,6 @@ ENTRY(stub_rt_sigreturn)
 
 /* 0(%rsp): interrupt number */ 
        .macro interrupt func
-       CFI_STARTPROC   simple
-       CFI_DEF_CFA     rsp,(SS-RDI)
-       CFI_REL_OFFSET  rsp,(RSP-ORIG_RAX)
-       CFI_REL_OFFSET  rip,(RIP-ORIG_RAX)
        cld
 #ifdef CONFIG_DEBUG_INFO
        SAVE_ALL        
@@ -425,23 +495,27 @@ ENTRY(stub_rt_sigreturn)
        swapgs  
 1:     incl    %gs:pda_irqcount        # RED-PEN should check preempt count
        movq %gs:pda_irqstackptr,%rax
-       cmoveq %rax,%rsp                                                        
+       cmoveq %rax,%rsp /*todo This needs CFI annotation! */
        pushq %rdi                      # save old stack        
+       CFI_ADJUST_CFA_OFFSET   8
        call \func
        .endm
 
 ENTRY(common_interrupt)
+       XCPT_FRAME
        interrupt do_IRQ
        /* 0(%rsp): oldrsp-ARGOFFSET */
-ret_from_intr:         
+ret_from_intr:
        popq  %rdi
+       CFI_ADJUST_CFA_OFFSET   -8
        cli     
        decl %gs:pda_irqcount
 #ifdef CONFIG_DEBUG_INFO
        movq RBP(%rdi),%rbp
+       CFI_DEF_CFA_REGISTER    rsp
 #endif
-       leaq ARGOFFSET(%rdi),%rsp
-exit_intr:             
+       leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
+exit_intr:
        GET_THREAD_INFO(%rcx)
        testl $3,CS-ARGOFFSET(%rsp)
        je retint_kernel
@@ -453,9 +527,10 @@ exit_intr:
         */             
 retint_with_reschedule:
        movl $_TIF_WORK_MASK,%edi
-retint_check:                  
+retint_check:
        movl threadinfo_flags(%rcx),%edx
        andl %edi,%edx
+       CFI_REMEMBER_STATE
        jnz  retint_careful
 retint_swapgs:         
        swapgs 
@@ -476,14 +551,17 @@ bad_iret:
        jmp do_exit                     
        .previous       
        
-       /* edi: workmask, edx: work */  
+       /* edi: workmask, edx: work */
 retint_careful:
+       CFI_RESTORE_STATE
        bt    $TIF_NEED_RESCHED,%edx
        jnc   retint_signal
        sti
        pushq %rdi
+       CFI_ADJUST_CFA_OFFSET   8
        call  schedule
        popq %rdi               
+       CFI_ADJUST_CFA_OFFSET   -8
        GET_THREAD_INFO(%rcx)
        cli
        jmp retint_check
@@ -523,7 +601,9 @@ retint_kernel:
  * APIC interrupts.
  */            
        .macro apicinterrupt num,func
+       INTR_FRAME
        pushq $\num-256
+       CFI_ADJUST_CFA_OFFSET 8
        interrupt \func
        jmp ret_from_intr
        CFI_ENDPROC
@@ -536,8 +616,19 @@ ENTRY(thermal_interrupt)
 ENTRY(reschedule_interrupt)
        apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
 
-ENTRY(invalidate_interrupt)
-       apicinterrupt INVALIDATE_TLB_VECTOR,smp_invalidate_interrupt
+       .macro INVALIDATE_ENTRY num
+ENTRY(invalidate_interrupt\num)
+       apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt 
+       .endm
+
+       INVALIDATE_ENTRY 0
+       INVALIDATE_ENTRY 1
+       INVALIDATE_ENTRY 2
+       INVALIDATE_ENTRY 3
+       INVALIDATE_ENTRY 4
+       INVALIDATE_ENTRY 5
+       INVALIDATE_ENTRY 6
+       INVALIDATE_ENTRY 7
 
 ENTRY(call_function_interrupt)
        apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
@@ -558,16 +649,23 @@ ENTRY(spurious_interrupt)
  * Exception entry points.
  */            
        .macro zeroentry sym
+       INTR_FRAME
        pushq $0        /* push error code/oldrax */ 
+       CFI_ADJUST_CFA_OFFSET 8
        pushq %rax      /* push real oldrax to the rdi slot */ 
+       CFI_ADJUST_CFA_OFFSET 8
        leaq  \sym(%rip),%rax
        jmp error_entry
+       CFI_ENDPROC
        .endm   
 
        .macro errorentry sym
+       XCPT_FRAME
        pushq %rax
+       CFI_ADJUST_CFA_OFFSET 8
        leaq  \sym(%rip),%rax
        jmp error_entry
+       CFI_ENDPROC
        .endm
 
        /* error code is on the stack already */
@@ -594,10 +692,7 @@ ENTRY(spurious_interrupt)
  * and the exception handler in %rax.  
  */                                            
 ENTRY(error_entry)
-       CFI_STARTPROC   simple
-       CFI_DEF_CFA     rsp,(SS-RDI)
-       CFI_REL_OFFSET  rsp,(RSP-RDI)
-       CFI_REL_OFFSET  rip,(RIP-RDI)
+       _frame RDI
        /* rdi slot contains rax, oldrax contains error code */
        cld     
        subq  $14*8,%rsp
@@ -679,7 +774,9 @@ error_kernelspace:
        /* Reload gs selector with exception handling */
        /* edi:  new selector */ 
 ENTRY(load_gs_index)
+       CFI_STARTPROC
        pushf
+       CFI_ADJUST_CFA_OFFSET 8
        cli
         swapgs
 gs_change:     
@@ -687,7 +784,9 @@ gs_change:
 2:     mfence          /* workaround */
        swapgs
         popf
+       CFI_ADJUST_CFA_OFFSET -8
         ret
+       CFI_ENDPROC
        
         .section __ex_table,"a"
         .align 8
@@ -799,7 +898,7 @@ ENTRY(device_not_available)
 
        /* runs on exception stack */
 KPROBE_ENTRY(debug)
-       CFI_STARTPROC
+       INTR_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug
@@ -809,9 +908,9 @@ KPROBE_ENTRY(debug)
 
        /* runs on exception stack */   
 ENTRY(nmi)
-       CFI_STARTPROC
+       INTR_FRAME
        pushq $-1
-       CFI_ADJUST_CFA_OFFSET 8         
+       CFI_ADJUST_CFA_OFFSET 8
        paranoidentry do_nmi
        /*
         * "Paranoid" exit path from exception stack.
@@ -877,7 +976,7 @@ ENTRY(reserved)
 
        /* runs on exception stack */
 ENTRY(double_fault)
-       CFI_STARTPROC
+       XCPT_FRAME
        paranoidentry do_double_fault
        jmp paranoid_exit
        CFI_ENDPROC
@@ -890,7 +989,7 @@ ENTRY(segment_not_present)
 
        /* runs on exception stack */
 ENTRY(stack_segment)
-       CFI_STARTPROC
+       XCPT_FRAME
        paranoidentry do_stack_segment
        jmp paranoid_exit
        CFI_ENDPROC
@@ -911,7 +1010,7 @@ ENTRY(spurious_interrupt_bug)
 #ifdef CONFIG_X86_MCE
        /* runs on exception stack */
 ENTRY(machine_check)
-       CFI_STARTPROC
+       INTR_FRAME
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8 
        paranoidentry do_machine_check
@@ -923,14 +1022,19 @@ ENTRY(call_debug)
        zeroentry do_call_debug
 
 ENTRY(call_softirq)
+       CFI_STARTPROC
        movq %gs:pda_irqstackptr,%rax
        pushq %r15
+       CFI_ADJUST_CFA_OFFSET 8
        movq %rsp,%r15
+       CFI_DEF_CFA_REGISTER    r15
        incl %gs:pda_irqcount
        cmove %rax,%rsp
        call __do_softirq
        movq %r15,%rsp
+       CFI_DEF_CFA_REGISTER    rsp
        decl %gs:pda_irqcount
        popq %r15
+       CFI_ADJUST_CFA_OFFSET -8
        ret
-
+       CFI_ENDPROC
index b1c144f73149854da5e9bb277e4309e281b60ba3..7a64ea181788c62e3c6a8e9e07a378ffa0a23ac0 100644 (file)
@@ -45,7 +45,7 @@ void __init clustered_apic_check(void)
        u8 clusters, max_cluster;
        u8 id;
        u8 cluster_cnt[NUM_APIC_CLUSTERS];
-       int num_cpus = 0;
+       int max_apic = 0;
 
 #if defined(CONFIG_ACPI)
        /*
@@ -64,14 +64,15 @@ void __init clustered_apic_check(void)
                id = bios_cpu_apicid[i];
                if (id == BAD_APICID)
                        continue;
-               num_cpus++;
+               if (id > max_apic)
+                       max_apic = id;
                cluster_cnt[APIC_CLUSTERID(id)]++;
        }
 
        /* Don't use clustered mode on AMD platforms. */
        if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
                genapic = &apic_physflat;
-#ifndef CONFIG_CPU_HOTPLUG
+#ifndef CONFIG_HOTPLUG_CPU
                /* In the CPU hotplug case we cannot use broadcast mode
                   because that opens a race when a CPU is removed.
                   Stay at physflat mode in this case.
@@ -79,7 +80,7 @@ void __init clustered_apic_check(void)
                   we have ACPI platform support for CPU hotplug
                   we should detect hotplug capablity from ACPI tables and
                   only do this when really needed. -AK */
-               if (num_cpus <= 8)
+               if (max_apic <= 8)
                        genapic = &apic_flat;
 #endif
                goto print;
@@ -103,9 +104,14 @@ void __init clustered_apic_check(void)
         * (We don't use lowest priority delivery + HW APIC IRQ steering, so
         * can ignore the clustered logical case and go straight to physical.)
         */
-       if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
+       if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster) {
+#ifdef CONFIG_HOTPLUG_CPU
+               /* Don't use APIC shortcuts in CPU hotplug to avoid races */
+               genapic = &apic_physflat;
+#else
                genapic = &apic_flat;
-       else
+#endif
+       } else
                genapic = &apic_cluster;
 
 print:
index f6523dd1bc0938fb6f21ff811af0b8292d77ca46..a472d62f899a87a8037a737663c09c3f507bbd77 100644 (file)
@@ -51,10 +51,10 @@ static void cluster_init_apic_ldr(void)
                count = 3;
        id = my_cluster | (1UL << count);
        x86_cpu_to_log_apicid[smp_processor_id()] = id;
-       apic_write_around(APIC_DFR, APIC_DFR_CLUSTER);
+       apic_write(APIC_DFR, APIC_DFR_CLUSTER);
        val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
        val |= SET_APIC_LOGICAL_ID(id);
-       apic_write_around(APIC_LDR, val);
+       apic_write(APIC_LDR, val);
 }
 
 /* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
index adc96282a9e2186f637f85576afdff2d6f4756be..9da3edb799ea543042776664db789a59b7418163 100644 (file)
@@ -38,10 +38,10 @@ static void flat_init_apic_ldr(void)
        num = smp_processor_id();
        id = 1UL << num;
        x86_cpu_to_log_apicid[num] = id;
-       apic_write_around(APIC_DFR, APIC_DFR_FLAT);
+       apic_write(APIC_DFR, APIC_DFR_FLAT);
        val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
        val |= SET_APIC_LOGICAL_ID(id);
-       apic_write_around(APIC_LDR, val);
+       apic_write(APIC_LDR, val);
 }
 
 static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
@@ -62,7 +62,7 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
         * prepare target chip field
         */
        cfg = __prepare_ICR2(mask);
-       apic_write_around(APIC_ICR2, cfg);
+       apic_write(APIC_ICR2, cfg);
 
        /*
         * program the ICR
@@ -72,14 +72,24 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
        /*
         * Send the IPI. The write to APIC_ICR fires this off.
         */
-       apic_write_around(APIC_ICR, cfg);
+       apic_write(APIC_ICR, cfg);
        local_irq_restore(flags);
 }
 
 static void flat_send_IPI_allbutself(int vector)
 {
+#ifndef CONFIG_HOTPLUG_CPU
        if (((num_online_cpus()) - 1) >= 1)
                __send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL);
+#else
+       cpumask_t allbutme = cpu_online_map;
+       int me = get_cpu(); /* Ensure we are not preempted when we clear */
+       cpu_clear(me, allbutme);
+
+       if (!cpus_empty(allbutme))
+               flat_send_IPI_mask(allbutme, vector);
+       put_cpu();
+#endif
 }
 
 static void flat_send_IPI_all(int vector)
@@ -167,9 +177,9 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
 
 struct genapic apic_physflat =  {
        .name = "physical flat",
-       .int_delivery_mode = dest_LowestPrio,
+       .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
-       .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_LOWEST,
+       .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
        .target_cpus = physflat_target_cpus,
        .apic_id_registered = flat_apic_id_registered,
        .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
index 98ff5eb32b9af5db22035c0da04cfe2bf9764367..4592bf21fcafa32e34d580a113255e6f61d1b754 100644 (file)
@@ -270,7 +270,7 @@ ENTRY(level3_kernel_pgt)
 .org 0x4000
 ENTRY(level2_ident_pgt)
        /* 40MB for bootup.     */
-       .quad   0x0000000000000283
+       .quad   0x0000000000000183
        .quad   0x0000000000200183
        .quad   0x0000000000400183
        .quad   0x0000000000600183
index a891690951299912495b8da4915210e73b524988..b2a238b5a17ed36cc7a071be01f62231d80cc5c0 100644 (file)
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/apic.h>
 
-#include <linux/irq.h>
-
 /*
  * Common place to define all x86 IRQ vectors
  *
@@ -486,7 +483,14 @@ void spurious_interrupt(void);
 void error_interrupt(void);
 void reschedule_interrupt(void);
 void call_function_interrupt(void);
-void invalidate_interrupt(void);
+void invalidate_interrupt0(void);
+void invalidate_interrupt1(void);
+void invalidate_interrupt2(void);
+void invalidate_interrupt3(void);
+void invalidate_interrupt4(void);
+void invalidate_interrupt5(void);
+void invalidate_interrupt6(void);
+void invalidate_interrupt7(void);
 void thermal_interrupt(void);
 void i8254_timer_resume(void);
 
@@ -562,8 +566,15 @@ void __init init_IRQ(void)
         */
        set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
 
-       /* IPI for invalidation */
-       set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+       /* IPIs for invalidation */
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
+       set_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
 
        /* IPI for generic function call */
        set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
index c4dc9149115741cf4b48c385adf8a49ec91979a8..e0ba5c1043fd23f71e48e236aebcb18b41d3934a 100644 (file)
@@ -44,6 +44,6 @@ EXPORT_SYMBOL(init_task);
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */ 
-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp;
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
 
 #define ALIGN_TO_4K __attribute__((section(".data.init_task")))
index 5f1529be1237495ba9a81757ec91c89c684dc1ef..522944a000ad9c8755ad529ba0c74bff3353c897 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -45,6 +44,8 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
 
 static int no_timer_check;
 
+int disable_timer_pin_1 __initdata;
+
 static DEFINE_SPINLOCK(ioapic_lock);
 
 /*
@@ -298,6 +299,15 @@ void __init check_ioapic(void)
 #endif
                                        /* RED-PEN skip them on mptables too? */
                                        return;
+                               case PCI_VENDOR_ID_ATI:
+                                       /* All timer interrupts on atiixp
+                                          are doubled. Disable one. */
+                                       if (disable_timer_pin_1 == 0) {
+                                               disable_timer_pin_1 = 1;
+                                               printk(KERN_INFO
+               "ATI board detected. Disabling timer pin 1.\n");
+                                       }
+                                       return;
                                } 
 
                                /* No multi-function device? */
@@ -1022,13 +1032,11 @@ void __apicdebuginit print_local_APIC(void * dummy)
        v = apic_read(APIC_TASKPRI);
        printk(KERN_DEBUG "... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
 
-       if (APIC_INTEGRATED(ver)) {                     /* !82489DX */
-               v = apic_read(APIC_ARBPRI);
-               printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
-                       v & APIC_ARBPRI_MASK);
-               v = apic_read(APIC_PROCPRI);
-               printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
-       }
+       v = apic_read(APIC_ARBPRI);
+       printk(KERN_DEBUG "... APIC ARBPRI: %08x (%02x)\n", v,
+               v & APIC_ARBPRI_MASK);
+       v = apic_read(APIC_PROCPRI);
+       printk(KERN_DEBUG "... APIC PROCPRI: %08x\n", v);
 
        v = apic_read(APIC_EOI);
        printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
@@ -1048,12 +1056,8 @@ void __apicdebuginit print_local_APIC(void * dummy)
        printk(KERN_DEBUG "... APIC IRR field:\n");
        print_APIC_bitfield(APIC_IRR);
 
-       if (APIC_INTEGRATED(ver)) {             /* !82489DX */
-               if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
-                       apic_write(APIC_ESR, 0);
-               v = apic_read(APIC_ESR);
-               printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
-       }
+       v = apic_read(APIC_ESR);
+       printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
 
        v = apic_read(APIC_ICR);
        printk(KERN_DEBUG "... APIC ICR: %08x\n", v);
@@ -1665,6 +1669,8 @@ static inline void check_timer(void)
                                setup_nmi();
                                enable_8259A_irq(0);
                        }
+                       if (disable_timer_pin_1 > 0)
+                               clear_IO_APIC_pin(0, pin1);
                        return;
                }
                clear_IO_APIC_pin(0, pin1);
index 849a20aec7ca05e4cb5067f44010e2ca830f34e6..d6a04a8320a38d475a3780488b856ecba23fe66b 100644 (file)
@@ -99,7 +99,6 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
        unsigned irq = regs->orig_rax & 0xff;
 
        irq_enter();
-       BUG_ON(irq > 256);
 
        __do_IRQ(irq, regs);
        irq_exit();
index 8aa56736cde3805fe8b38b84733e176914ae14be..969365c0771b242f5b64071e294bba4cd114fca9 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/cpu.h>
 #include <linux/percpu.h>
+#include <linux/ctype.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -56,15 +57,19 @@ void mce_log(struct mce *mce)
        smp_wmb();
        for (;;) {
                entry = rcu_dereference(mcelog.next);
-               /* When the buffer fills up discard new entries. Assume 
-                  that the earlier errors are the more interesting. */
-               if (entry >= MCE_LOG_LEN) {
-                       set_bit(MCE_OVERFLOW, &mcelog.flags);
-                       return;
+               for (;;) {
+                       /* When the buffer fills up discard new entries. Assume
+                          that the earlier errors are the more interesting. */
+                       if (entry >= MCE_LOG_LEN) {
+                               set_bit(MCE_OVERFLOW, &mcelog.flags);
+                               return;
+                       }
+                       /* Old left over entry. Skip. */
+                       if (mcelog.entry[entry].finished) {
+                               entry++;
+                               continue;
+                       }
                }
-               /* Old left over entry. Skip. */
-               if (mcelog.entry[entry].finished)
-                       continue;
                smp_rmb();
                next = entry + 1;
                if (cmpxchg(&mcelog.next, entry, next) == entry)
@@ -404,9 +409,15 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
        }
 
        err = 0;
-       for (i = 0; i < next; i++) {
-               if (!mcelog.entry[i].finished)
-                       continue;
+       for (i = 0; i < next; i++) {            
+               unsigned long start = jiffies;
+               while (!mcelog.entry[i].finished) {
+                       if (!time_before(jiffies, start + 2)) {
+                               memset(mcelog.entry + i,0, sizeof(struct mce));
+                               continue;
+                       }
+                       cpu_relax();
+               }
                smp_rmb();
                err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
                buf += sizeof(struct mce); 
@@ -479,6 +490,7 @@ static int __init mcheck_disable(char *str)
 
 /* mce=off disables machine check. Note you can reenable it later
    using sysfs.
+   mce=TOLERANCELEVEL (number, see above)
    mce=bootlog Log MCEs from before booting. Disabled by default to work
    around buggy BIOS that leave bogus MCEs.  */
 static int __init mcheck_enable(char *str)
@@ -489,6 +501,8 @@ static int __init mcheck_enable(char *str)
                mce_dont_init = 1;
        else if (!strcmp(str, "bootlog"))
                mce_bootlog = 1;
+       else if (isdigit(str[0]))
+               get_option(&str, &tolerant);
        else
                printk("mce= argument %s ignored. Please use /sys", str); 
        return 0;
@@ -501,10 +515,12 @@ __setup("mce", mcheck_enable);
  * Sysfs support
  */ 
 
-/* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */
+/* On resume clear all MCE state. Don't want to see leftovers from the BIOS.
+   Only one CPU is active at this time, the others get readded later using
+   CPU hotplug. */
 static int mce_resume(struct sys_device *dev)
 {
-       on_each_cpu(mce_init, NULL, 1, 1);
+       mce_init(NULL);
        return 0;
 }
 
index 8d8ed6ae1d0c8d880f96558b7a8f865a80ea2ac5..f16d38d09dafeadcafc6d1e6413617c96eeeb8d4 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/config.h>
@@ -46,8 +45,6 @@ int acpi_found_madt;
 int apic_version [MAX_APICS];
 unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-unsigned char pci_bus_to_node [256];
-EXPORT_SYMBOL(pci_bus_to_node);
 
 static int mp_current_pci_id = 0;
 /* I/O APIC entries */
@@ -705,7 +702,7 @@ void __init mp_register_lapic (
 
        processor.mpc_type = MP_PROCESSOR;
        processor.mpc_apicid = id;
-       processor.mpc_apicver = 0x10; /* TBD: lapic version */
+       processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
        processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
        processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
        processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
deleted file mode 100644 (file)
index 598953a..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *   
- *   Copyright 2000 H. Peter Anvin - 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, Inc., 675 Mass Ave, Cambridge MA 02139,
- *   USA; either version 2 of the License, or (at your option) any later
- *   version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * msr.c
- *
- * x86 MSR access device
- *
- * This device is accessed by lseek() to the appropriate register number
- * and then read/write in chunks of 8 bytes.  A larger size means multiple
- * reads or writes of the same register.
- *
- * This driver uses /dev/cpu/%d/msr where %d is the minor number, and on
- * an SMP box will direct the access to CPU %d.
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/* Note: "err" is handled in a funny way below.  Otherwise one version
-   of gcc or another breaks. */
-
-static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
-{
-       int err;
-
-       asm volatile ("1:       wrmsr\n"
-                     "2:\n"
-                     ".section .fixup,\"ax\"\n"
-                     "3:       movl %4,%0\n"
-                     " jmp 2b\n"
-                     ".previous\n"
-                     ".section __ex_table,\"a\"\n"
-                     " .align 8\n" "   .quad 1b,3b\n" ".previous":"=&bDS" (err)
-                     :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
-
-       return err;
-}
-
-static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
-{
-       int err;
-
-       asm volatile ("1:       rdmsr\n"
-                     "2:\n"
-                     ".section .fixup,\"ax\"\n"
-                     "3:       movl %4,%0\n"
-                     " jmp 2b\n"
-                     ".previous\n"
-                     ".section __ex_table,\"a\"\n"
-                     " .align 8\n"
-                     " .quad 1b,3b\n"
-                     ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
-                     :"c"(reg), "i"(-EIO), "0"(0));
-
-       return err;
-}
-
-#ifdef CONFIG_SMP
-
-struct msr_command {
-       int cpu;
-       int err;
-       u32 reg;
-       u32 data[2];
-};
-
-static void msr_smp_wrmsr(void *cmd_block)
-{
-       struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-       if (cmd->cpu == smp_processor_id())
-               cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
-}
-
-static void msr_smp_rdmsr(void *cmd_block)
-{
-       struct msr_command *cmd = (struct msr_command *)cmd_block;
-
-       if (cmd->cpu == smp_processor_id())
-               cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
-}
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-       struct msr_command cmd;
-       int ret;
-
-       preempt_disable();
-       if (cpu == smp_processor_id()) {
-               ret = wrmsr_eio(reg, eax, edx);
-       } else {
-               cmd.cpu = cpu;
-               cmd.reg = reg;
-               cmd.data[0] = eax;
-               cmd.data[1] = edx;
-
-               smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
-               ret = cmd.err;
-       }
-       preempt_enable();
-       return ret;
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
-{
-       struct msr_command cmd;
-       int ret;
-
-       preempt_disable();
-       if (cpu == smp_processor_id()) {
-               ret = rdmsr_eio(reg, eax, edx);
-       } else {
-               cmd.cpu = cpu;
-               cmd.reg = reg;
-
-               smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
-
-               *eax = cmd.data[0];
-               *edx = cmd.data[1];
-
-               ret = cmd.err;
-       }
-       preempt_enable();
-       return ret;
-}
-
-#else                          /* ! CONFIG_SMP */
-
-static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
-{
-       return wrmsr_eio(reg, eax, edx);
-}
-
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
-{
-       return rdmsr_eio(reg, eax, edx);
-}
-
-#endif                         /* ! CONFIG_SMP */
-
-static loff_t msr_seek(struct file *file, loff_t offset, int orig)
-{
-       loff_t ret = -EINVAL;
-
-       lock_kernel();
-       switch (orig) {
-       case 0:
-               file->f_pos = offset;
-               ret = file->f_pos;
-               break;
-       case 1:
-               file->f_pos += offset;
-               ret = file->f_pos;
-       }
-       unlock_kernel();
-       return ret;
-}
-
-static ssize_t msr_read(struct file *file, char __user * buf,
-                       size_t count, loff_t * ppos)
-{
-       u32 __user *tmp = (u32 __user *) buf;
-       u32 data[2];
-       size_t rv;
-       u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
-       int err;
-
-       if (count % 8)
-               return -EINVAL; /* Invalid chunk size */
-
-       for (rv = 0; count; count -= 8) {
-               err = do_rdmsr(cpu, reg, &data[0], &data[1]);
-               if (err)
-                       return err;
-               if (copy_to_user(tmp, &data, 8))
-                       return -EFAULT;
-               tmp += 2;
-       }
-
-       return ((char __user *)tmp) - buf;
-}
-
-static ssize_t msr_write(struct file *file, const char __user *buf,
-                        size_t count, loff_t *ppos)
-{
-       const u32 __user *tmp = (const u32 __user *)buf;
-       u32 data[2];
-       size_t rv;
-       u32 reg = *ppos;
-       int cpu = iminor(file->f_dentry->d_inode);
-       int err;
-
-       if (count % 8)
-               return -EINVAL; /* Invalid chunk size */
-
-       for (rv = 0; count; count -= 8) {
-               if (copy_from_user(&data, tmp, 8))
-                       return -EFAULT;
-               err = do_wrmsr(cpu, reg, data[0], data[1]);
-               if (err)
-                       return err;
-               tmp += 2;
-       }
-
-       return ((char __user *)tmp) - buf;
-}
-
-static int msr_open(struct inode *inode, struct file *file)
-{
-       unsigned int cpu = iminor(file->f_dentry->d_inode);
-       struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-
-       if (cpu >= NR_CPUS || !cpu_online(cpu))
-               return -ENXIO;  /* No such CPU */
-       if (!cpu_has(c, X86_FEATURE_MSR))
-               return -EIO;    /* MSR not supported */
-
-       return 0;
-}
-
-/*
- * File operations we support
- */
-static struct file_operations msr_fops = {
-       .owner = THIS_MODULE,
-       .llseek = msr_seek,
-       .read = msr_read,
-       .write = msr_write,
-       .open = msr_open,
-};
-
-static int __init msr_init(void)
-{
-       if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
-               printk(KERN_ERR "msr: unable to get major %d for msr\n",
-                      MSR_MAJOR);
-               return -EBUSY;
-       }
-
-       return 0;
-}
-
-static void __exit msr_exit(void)
-{
-       unregister_chrdev(MSR_MAJOR, "cpu/msr");
-}
-
-module_init(msr_init);
-module_exit(msr_exit)
-
-MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
-MODULE_DESCRIPTION("x86 generic MSR driver");
-MODULE_LICENSE("GPL");
index caf164959e197d25f100b54c1195ef19257e9c72..4388b8a5bae761fd04a7ab70af00d5a0b8b04043 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/smp_lock.h>
@@ -488,8 +487,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
                                                        == NOTIFY_STOP) {
                                local_set(&__get_cpu_var(alert_counter), 0);
                                return;
-                       } 
-                       die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
+                       }
+                       die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
                }
        } else {
                __get_cpu_var(last_irq_sum) = sum;
index 57f35c68aa34d0eb4255a919e9bca929622feed1..cf0a0315d586a15bc17dcd2de072956a00dc0d2e 100644 (file)
@@ -191,11 +191,9 @@ static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
 {
        struct page *page;
        int node;
-       if (dev->bus == &pci_bus_type) {
-               cpumask_t mask;
-               mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
-               node = cpu_to_node(first_cpu(mask));
-       } else
+       if (dev->bus == &pci_bus_type)
+               node = pcibus_to_node(to_pci_dev(dev)->bus);
+       else
                node = numa_node_id();
        page = alloc_pages_node(node, gfp, order);
        return page ? page_address(page) : NULL;
index 8661f82ac70b409d96a70b31b84ad87c485fbd30..b5a89c0bdf5914851fe32710b0b808587dfb6c32 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
 #include <linux/random.h>
@@ -123,6 +122,7 @@ static void poll_idle (void)
                        : :
                        "i" (_TIF_NEED_RESCHED), 
                        "m" (current_thread_info()->flags));
+               clear_thread_flag(TIF_POLLING_NRFLAG);
        } else {
                set_need_resched();
        }
@@ -271,8 +271,11 @@ void __show_regs(struct pt_regs * regs)
 
        printk("\n");
        print_modules();
-       printk("Pid: %d, comm: %.20s %s %s\n", 
-              current->pid, current->comm, print_tainted(), system_utsname.release);
+       printk("Pid: %d, comm: %.20s %s %s %.*s\n",
+               current->pid, current->comm, print_tainted(),
+               system_utsname.release,
+               (int)strcspn(system_utsname.version, " "),
+               system_utsname.version);
        printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
        printk_address(regs->rip); 
        printk("\nRSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss, regs->rsp, regs->eflags);
@@ -482,33 +485,6 @@ out:
        return err;
 }
 
-/*
- * This function selects if the context switch from prev to next
- * has to tweak the TSC disable bit in the cr4.
- */
-static inline void disable_tsc(struct task_struct *prev_p,
-                              struct task_struct *next_p)
-{
-       struct thread_info *prev, *next;
-
-       /*
-        * gcc should eliminate the ->thread_info dereference if
-        * has_secure_computing returns 0 at compile time (SECCOMP=n).
-        */
-       prev = prev_p->thread_info;
-       next = next_p->thread_info;
-
-       if (has_secure_computing(prev) || has_secure_computing(next)) {
-               /* slow path here */
-               if (has_secure_computing(prev) &&
-                   !has_secure_computing(next)) {
-                       write_cr4(read_cr4() & ~X86_CR4_TSD);
-               } else if (!has_secure_computing(prev) &&
-                          has_secure_computing(next))
-                       write_cr4(read_cr4() | X86_CR4_TSD);
-       }
-}
-
 /*
  * This special macro can be used to load a debugging register
  */
@@ -627,8 +603,6 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
                }
        }
 
-       disable_tsc(prev_p, next_p);
-
        return prev_p;
 }
 
index 0511d8087910d077741a93ce811a4241ee67e0e2..351d8d64c2fbf45cff433c18fe38cba1156f2b7f 100644 (file)
@@ -336,6 +336,11 @@ static __init void parse_cmdline_early (char ** cmdline_p)
 #endif
 #endif
 
+               if (!memcmp(from, "disable_timer_pin_1", 19))
+                       disable_timer_pin_1 = 1;
+               if (!memcmp(from, "enable_timer_pin_1", 18))
+                       disable_timer_pin_1 = -1;
+
                if (!memcmp(from, "nolapic", 7) ||
                    !memcmp(from, "disableapic", 11))
                        disable_apic = 1;
@@ -755,6 +760,24 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
        }
 }
 
+#ifdef CONFIG_NUMA
+static int nearby_node(int apicid)
+{
+       int i;
+       for (i = apicid - 1; i >= 0; i--) {
+               int node = apicid_to_node[i];
+               if (node != NUMA_NO_NODE && node_online(node))
+                       return node;
+       }
+       for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
+               int node = apicid_to_node[i];
+               if (node != NUMA_NO_NODE && node_online(node))
+                       return node;
+       }
+       return first_node(node_online_map); /* Shouldn't happen */
+}
+#endif
+
 /*
  * On a AMD dual core setup the lower bits of the APIC id distingush the cores.
  * Assumes number of cores is a power of two.
@@ -763,8 +786,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        int cpu = smp_processor_id();
-       int node = 0;
        unsigned bits;
+#ifdef CONFIG_NUMA
+       int node = 0;
+       unsigned apicid = phys_proc_id[cpu];
+#endif
 
        bits = 0;
        while ((1 << bits) < c->x86_num_cores)
@@ -776,20 +802,32 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
        phys_proc_id[cpu] >>= bits;
 
 #ifdef CONFIG_NUMA
-       /* When an ACPI SRAT table is available use the mappings from SRAT
-          instead. */
-       if (acpi_numa <= 0) {
-               node = phys_proc_id[cpu];
-               if (!node_online(node))
-                       node = first_node(node_online_map);
-               cpu_to_node[cpu] = node;
-       } else {
-               node = cpu_to_node[cpu];
-       }
+       node = phys_proc_id[cpu];
+       if (apicid_to_node[apicid] != NUMA_NO_NODE)
+               node = apicid_to_node[apicid];
+       if (!node_online(node)) {
+               /* Two possibilities here:
+                  - The CPU is missing memory and no node was created.
+                  In that case try picking one from a nearby CPU
+                  - The APIC IDs differ from the HyperTransport node IDs
+                  which the K8 northbridge parsing fills in.
+                  Assume they are all increased by a constant offset,
+                  but in the same order as the HT nodeids.
+                  If that doesn't result in a usable node fall back to the
+                  path for the previous case.  */
+               int ht_nodeid = apicid - (phys_proc_id[0] << bits);
+               if (ht_nodeid >= 0 &&
+                   apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+                       node = apicid_to_node[ht_nodeid];
+               /* Pick a nearby node */
+               if (!node_online(node))
+                       node = nearby_node(apicid);
+       }
+       cpu_to_node[cpu] = node;
+
+       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
+                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
-
-       printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
-                       cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
 #endif
 }
 
@@ -909,6 +947,25 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
                return 1;
 }
 
+static void srat_detect_node(void)
+{
+#ifdef CONFIG_NUMA
+       unsigned apicid, node;
+       int cpu = smp_processor_id();
+
+       /* Don't do the funky fallback heuristics the AMD version employs
+          for now. */
+       apicid = phys_proc_id[cpu];
+       node = apicid_to_node[apicid];
+       if (node == NUMA_NO_NODE)
+               node = 0;
+       cpu_to_node[cpu] = node;
+
+       if (acpi_numa > 0)
+               printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
+#endif
+}
+
 static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
        /* Cache sizes */
@@ -927,9 +984,11 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
        if (c->x86 >= 15)
                set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
        c->x86_num_cores = intel_num_cpu_cores(c);
+
+       srat_detect_node();
 }
 
-void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
+static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
        char *v = c->x86_vendor_id;
 
index e3ffcacc8c90bf40d17a778c684401a9d66b17d3..bd33be24a386717d3c402059ce49ba0dad3ab838 100644 (file)
@@ -94,7 +94,7 @@ void __init setup_per_cpu_areas(void)
                size = PERCPU_ENOUGH_ROOM;
 #endif
 
-       for (i = 0; i < NR_CPUS; i++) { 
+       for_each_cpu_mask (i, cpu_possible_map) {
                char *ptr;
 
                if (!NODE_DATA(cpu_to_node(i))) {
@@ -119,7 +119,6 @@ void pda_init(int cpu)
        asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); 
        wrmsrl(MSR_GS_BASE, cpu_pda + cpu);
 
-       pda->me = pda;
        pda->cpunumber = cpu; 
        pda->irqcount = -1;
        pda->kernelstack = 
index e5958220d6b8b8eaaca2f70d956efc249c3faa40..9db9dda161b40fe59df298406518bb4a867b0b61 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
@@ -29,6 +28,8 @@
 #include <asm/proto.h>
 #include <asm/apicdef.h>
 
+#define __cpuinit __init
+
 /*
  *     Smarter SMP flushing macros. 
  *             c/o Linus Torvalds.
  *     writing to user space from interrupts. (Its not allowed anyway).
  *
  *     Optimizations Manfred Spraul <manfred@colorfullife.com>
+ *
+ *     More scalable flush, from Andi Kleen
+ *
+ *     To avoid global state use 8 different call vectors.
+ *     Each CPU uses a specific vector to trigger flushes on other
+ *     CPUs. Depending on the received vector the target CPUs look into
+ *     the right per cpu variable for the flush data.
+ *
+ *     With more than 8 CPUs they are hashed to the 8 available
+ *     vectors. The limited global vector space forces us to this right now.
+ *     In future when interrupts are split into per CPU domains this could be
+ *     fixed, at the cost of triggering multiple IPIs in some cases.
  */
 
-static cpumask_t flush_cpumask;
-static struct mm_struct * flush_mm;
-static unsigned long flush_va;
-static DEFINE_SPINLOCK(tlbstate_lock);
+union smp_flush_state {
+       struct {
+               cpumask_t flush_cpumask;
+               struct mm_struct *flush_mm;
+               unsigned long flush_va;
 #define FLUSH_ALL      -1ULL
+               spinlock_t tlbstate_lock;
+       };
+       char pad[SMP_CACHE_BYTES];
+} ____cacheline_aligned;
+
+/* State is put into the per CPU data section, but padded
+   to a full cache line because other CPUs can access it and we don't
+   want false sharing in the per cpu data segment. */
+static DEFINE_PER_CPU(union smp_flush_state, flush_state);
 
 /*
  * We cannot call mmdrop() because we are in interrupt context, 
  * instead update mm->cpu_vm_mask.
  */
-static inline void leave_mm (unsigned long cpu)
+static inline void leave_mm(int cpu)
 {
        if (read_pda(mmu_state) == TLBSTATE_OK)
                BUG();
@@ -101,15 +124,25 @@ static inline void leave_mm (unsigned long cpu)
  *
  * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
  * 2) Leave the mm if we are in the lazy tlb mode.
+ *
+ * Interrupts are disabled.
  */
 
-asmlinkage void smp_invalidate_interrupt (void)
+asmlinkage void smp_invalidate_interrupt(struct pt_regs *regs)
 {
-       unsigned long cpu;
+       int cpu;
+       int sender;
+       union smp_flush_state *f;
 
-       cpu = get_cpu();
+       cpu = smp_processor_id();
+       /*
+        * orig_rax contains the interrupt vector - 256.
+        * Use that to determine where the sender put the data.
+        */
+       sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
+       f = &per_cpu(flush_state, sender);
 
-       if (!cpu_isset(cpu, flush_cpumask))
+       if (!cpu_isset(cpu, f->flush_cpumask))
                goto out;
                /* 
                 * This was a BUG() but until someone can quote me the
@@ -120,64 +153,63 @@ asmlinkage void smp_invalidate_interrupt (void)
                 * BUG();
                 */
                 
-       if (flush_mm == read_pda(active_mm)) {
+       if (f->flush_mm == read_pda(active_mm)) {
                if (read_pda(mmu_state) == TLBSTATE_OK) {
-                       if (flush_va == FLUSH_ALL)
+                       if (f->flush_va == FLUSH_ALL)
                                local_flush_tlb();
                        else
-                               __flush_tlb_one(flush_va);
+                               __flush_tlb_one(f->flush_va);
                } else
                        leave_mm(cpu);
        }
 out:
        ack_APIC_irq();
-       cpu_clear(cpu, flush_cpumask);
-       put_cpu_no_resched();
+       cpu_clear(cpu, f->flush_cpumask);
 }
 
 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
                                                unsigned long va)
 {
-       cpumask_t tmp;
-       /*
-        * A couple of (to be removed) sanity checks:
-        *
-        * - we do not send IPIs to not-yet booted CPUs.
-        * - current CPU must not be in mask
-        * - mask must exist :)
-        */
-       BUG_ON(cpus_empty(cpumask));
-       cpus_and(tmp, cpumask, cpu_online_map);
-       BUG_ON(!cpus_equal(tmp, cpumask));
-       BUG_ON(cpu_isset(smp_processor_id(), cpumask));
-       if (!mm)
-               BUG();
+       int sender;
+       union smp_flush_state *f;
 
-       /*
-        * I'm not happy about this global shared spinlock in the
-        * MM hot path, but we'll see how contended it is.
-        * Temporarily this turns IRQs off, so that lockups are
-        * detected by the NMI watchdog.
-        */
-       spin_lock(&tlbstate_lock);
-       
-       flush_mm = mm;
-       flush_va = va;
-       cpus_or(flush_cpumask, cpumask, flush_cpumask);
+       /* Caller has disabled preemption */
+       sender = smp_processor_id() % NUM_INVALIDATE_TLB_VECTORS;
+       f = &per_cpu(flush_state, sender);
+
+       /* Could avoid this lock when
+          num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
+          probably not worth checking this for a cache-hot lock. */
+       spin_lock(&f->tlbstate_lock);
+
+       f->flush_mm = mm;
+       f->flush_va = va;
+       cpus_or(f->flush_cpumask, cpumask, f->flush_cpumask);
 
        /*
         * We have to send the IPI only to
         * CPUs affected.
         */
-       send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+       send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+
+       while (!cpus_empty(f->flush_cpumask))
+               cpu_relax();
 
-       while (!cpus_empty(flush_cpumask))
-               mb();   /* nothing. lockup detection does not belong here */;
+       f->flush_mm = NULL;
+       f->flush_va = 0;
+       spin_unlock(&f->tlbstate_lock);
+}
 
-       flush_mm = NULL;
-       flush_va = 0;
-       spin_unlock(&tlbstate_lock);
+int __cpuinit init_smp_flush(void)
+{
+       int i;
+       for_each_cpu_mask(i, cpu_possible_map) {
+               spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+       }
+       return 0;
 }
+
+core_initcall(init_smp_flush);
        
 void flush_tlb_current_task(void)
 {
@@ -295,8 +327,11 @@ void unlock_ipi_call_lock(void)
 /*
  * this function sends a 'generic call function' IPI to one other CPU
  * in the system.
+ *
+ * cpu is a standard Linux logical CPU number.
  */
-static void __smp_call_function_single (int cpu, void (*func) (void *info), void *info,
+static void
+__smp_call_function_single(int cpu, void (*func) (void *info), void *info,
                                int nonatomic, int wait)
 {
        struct call_data_struct data;
index 90aeccd1519074c27b65524c6fa8bc601f0efb09..e12d7baeb33ec47ca0dc935f267dcc874693d5f6 100644 (file)
@@ -44,7 +44,6 @@
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
-#include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/thread_info.h>
 #include <linux/module.h>
@@ -58,6 +57,8 @@
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
 #include <asm/nmi.h>
+#include <asm/irq.h>
+#include <asm/hw_irq.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -413,8 +414,13 @@ void __cpuinit smp_callin(void)
 
        /*
         * Get our bogomips.
+        *
+        * Need to enable IRQs because it can take longer and then
+        * the NMI watchdog might kill us.
         */
+       local_irq_enable();
        calibrate_delay();
+       local_irq_disable();
        Dprintk("Stack at about %p\n",&cpuid);
 
        disable_APIC_timer();
@@ -540,8 +546,8 @@ static void inquire_remote_apic(int apicid)
                 */
                apic_wait_icr_idle();
 
-               apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
-               apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
+               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+               apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
 
                timeout = 0;
                do {
@@ -574,12 +580,12 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        /*
         * Turn INIT on target chip
         */
-       apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
        /*
         * Send IPI
         */
-       apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
+       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
                                | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
@@ -595,10 +601,10 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
        Dprintk("Deasserting INIT.\n");
 
        /* Target chip */
-       apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+       apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
        /* Send IPI */
-       apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+       apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
 
        Dprintk("Waiting for send to finish...\n");
        timeout = 0;
@@ -610,16 +616,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
 
        atomic_set(&init_deasserted, 1);
 
-       /*
-        * Should we send STARTUP IPIs ?
-        *
-        * Determine this based on the APIC version.
-        * If we don't have an integrated APIC, don't send the STARTUP IPIs.
-        */
-       if (APIC_INTEGRATED(apic_version[phys_apicid]))
-               num_starts = 2;
-       else
-               num_starts = 0;
+       num_starts = 2;
 
        /*
         * Run STARTUP IPI loop.
@@ -640,12 +637,11 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
                 */
 
                /* Target chip */
-               apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
+               apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
 
                /* Boot on the stack */
                /* Kick the second */
-               apic_write_around(APIC_ICR, APIC_DM_STARTUP
-                                       | (start_rip >> 12));
+               apic_write(APIC_ICR, APIC_DM_STARTUP | (start_rip >> 12));
 
                /*
                 * Give the other CPU some time to accept the IPI.
@@ -864,17 +860,6 @@ static __cpuinit void smp_cleanup_boot(void)
         * Reset trampoline flag
         */
        *((volatile int *) phys_to_virt(0x467)) = 0;
-
-#ifndef CONFIG_HOTPLUG_CPU
-       /*
-        * Free pages reserved for SMP bootup.
-        * When you add hotplug CPU support later remove this
-        * Note there is more work to be done for later CPU bootup.
-        */
-
-       free_page((unsigned long) __va(PAGE_SIZE));
-       free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE));
-#endif
 }
 
 /*
@@ -894,23 +879,6 @@ static __init void disable_smp(void)
        cpu_set(0, cpu_core_map[0]);
 }
 
-/*
- * Handle user cpus=... parameter.
- */
-static __init void enforce_max_cpus(unsigned max_cpus)
-{
-       int i, k;
-       k = 0;
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
-               if (++k > max_cpus) {
-                       cpu_clear(i, cpu_possible_map);
-                       cpu_clear(i, cpu_present_map);
-               }
-       }
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 /*
  * cpu_possible_map should be static, it cannot change as cpu's
@@ -999,8 +967,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        current_cpu_data = boot_cpu_data;
        current_thread_info()->cpu = 0;  /* needed? */
 
-       enforce_max_cpus(max_cpus);
-
 #ifdef CONFIG_HOTPLUG_CPU
        prefill_possible_map();
 #endif
index 0612640d91b1c31262d3022edd6ffac685190514..ebb9abf3ce6dae3269711f583b0ef2f827d148cb 100644 (file)
@@ -8,23 +8,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/sysrq.h>
-#include <linux/proc_fs.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/device.h>
+#include <linux/smp.h>
 #include <linux/suspend.h>
-#include <asm/uaccess.h>
-#include <asm/acpi.h>
-#include <asm/tlbflush.h>
-#include <asm/io.h>
 #include <asm/proto.h>
 
 struct saved_context saved_context;
index 53f8e1659511fe7ff7708c47c59c8ac6ab025c00..4d659e97df100b354fc07f4aaa4f39f86ca686ff 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 
 ENTRY(swsusp_arch_suspend)
 
index 7b6abe0582536f54f5c5aea12587d22d3ab92f1d..2373cb8b86250744018a1ecdd48fc7b6da21248a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/mc146818rtc.h>
-#include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
@@ -937,7 +936,6 @@ void __init time_init(void)
        vxtime.mode = VXTIME_TSC;
        vxtime.quot = (1000000L << 32) / vxtime_hz;
        vxtime.tsc_quot = (1000L << 32) / cpu_khz;
-       vxtime.hz = vxtime_hz;
        rdtscll_sync(&vxtime.last_tsc);
        setup_irq(0, &irq0);
 
index f238d6078a5a921fcf94c935903b9aaa3aac5bf0..b5e09e6b55368fbd58572ac8c775bd1fc77ab4a7 100644 (file)
@@ -47,9 +47,6 @@
 #include <asm/proto.h>
 #include <asm/nmi.h>
 
-#include <linux/irq.h>
-
-
 extern struct gate_struct idt_table[256]; 
 
 asmlinkage void divide_error(void);
@@ -324,13 +321,13 @@ void handle_BUG(struct pt_regs *regs)
        if (__copy_from_user(&f, (struct bug_frame *) regs->rip, 
                             sizeof(struct bug_frame)))
                return; 
-       if ((unsigned long)f.filename < __PAGE_OFFSET || 
+       if (f.filename >= 0 ||
            f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) 
                return;
-       if (__get_user(tmp, f.filename))
-               f.filename = "unmapped filename"; 
+       if (__get_user(tmp, (char *)(long)f.filename))
+               f.filename = (int)(long)"unmapped filename";
        printk("----------- [cut here ] --------- [please bite here ] ---------\n");
-       printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
+       printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line);
 } 
 
 #ifdef CONFIG_BUG
@@ -343,30 +340,33 @@ void out_of_line_bug(void)
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
 
-void oops_begin(void)
+unsigned long oops_begin(void)
 {
-       int cpu = safe_smp_processor_id(); 
-       /* racy, but better than risking deadlock. */ 
-       local_irq_disable();
+       int cpu = safe_smp_processor_id();
+       unsigned long flags;
+
+       /* racy, but better than risking deadlock. */
+       local_irq_save(flags);
        if (!spin_trylock(&die_lock)) { 
                if (cpu == die_owner) 
                        /* nested oops. should stop eventually */;
                else
-                       spin_lock(&die_lock); 
+                       spin_lock(&die_lock);
        }
-       die_owner = cpu; 
+       die_owner = cpu;
        console_verbose();
-       bust_spinlocks(1); 
+       bust_spinlocks(1);
+       return flags;
 }
 
-void oops_end(void)
+void oops_end(unsigned long flags)
 { 
        die_owner = -1;
-       bust_spinlocks(0); 
-       spin_unlock(&die_lock); 
+       bust_spinlocks(0);
+       spin_unlock_irqrestore(&die_lock, flags);
        if (panic_on_oops)
-               panic("Oops"); 
-} 
+               panic("Oops");
+}
 
 void __die(const char * str, struct pt_regs * regs, long err)
 {
@@ -392,10 +392,11 @@ void __die(const char * str, struct pt_regs * regs, long err)
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
-       oops_begin();
+       unsigned long flags = oops_begin();
+
        handle_BUG(regs);
        __die(str, regs, err);
-       oops_end();
+       oops_end(flags);
        do_exit(SIGSEGV); 
 }
 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
@@ -406,7 +407,8 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e
 
 void die_nmi(char *str, struct pt_regs *regs)
 {
-       oops_begin();
+       unsigned long flags = oops_begin();
+
        /*
         * We are in trouble anyway, lets at least try
         * to get a message out.
@@ -416,7 +418,7 @@ void die_nmi(char *str, struct pt_regs *regs)
        if (panic_on_timeout || panic_on_oops)
                panic("nmi watchdog");
        printk("console shuts up ...\n");
-       oops_end();
+       oops_end(flags);
        do_exit(SIGSEGV);
 }
 
@@ -790,13 +792,16 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
         */
        cwd = get_fpu_cwd(task);
        swd = get_fpu_swd(task);
-       switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+       switch (swd & ~cwd & 0x3f) {
                case 0x000:
                default:
                        break;
                case 0x001: /* Invalid Op */
-               case 0x041: /* Stack Fault */
-               case 0x241: /* Stack Fault | Direction */
+                       /*
+                        * swd & 0x240 == 0x040: Stack Underflow
+                        * swd & 0x240 == 0x240: Stack Overflow
+                        * User must clear the SF bit (0x40) if set
+                        */
                        info.si_code = FPE_FLTINV;
                        break;
                case 0x002: /* Denormalize */
index d4abb07af52dbef72da991331845b4438251a60b..6dd642cad2efd0074d2150edebe7d78080836850 100644 (file)
@@ -194,20 +194,7 @@ SECTIONS
 #endif
        }
 
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info) }
-  .debug_abbrev   0 : { *(.debug_abbrev) }
-  .debug_line     0 : { *(.debug_line) }
-  .debug_frame    0 : { *(.debug_frame) }
-  .debug_str      0 : { *(.debug_str) }
-  .debug_loc      0 : { *(.debug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames) }
-
-
-  .comment 0 : { *(.comment) }
+  STABS_DEBUG
+
+  DWARF_DEBUG
 }
index 2e5734425949648ea92bd8d7fd9e65e6f99a8ed5..70a0bd16085fbd3a4fe9bf6c7719e5b33cb54965 100644 (file)
@@ -107,7 +107,7 @@ static force_inline long time_syscall(long *t)
        return secs;
 }
 
-static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
+int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
 {
        if (unlikely(!__sysctl_vsyscall))
                return gettimeofday(tv,tz);
@@ -120,7 +120,7 @@ static int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz
 
 /* This will break when the xtime seconds get inaccurate, but that is
  * unlikely */
-static time_t __vsyscall(1) vtime(time_t *t)
+time_t __vsyscall(1) vtime(time_t *t)
 {
        if (unlikely(!__sysctl_vsyscall))
                return time_syscall(t);
@@ -129,12 +129,12 @@ static time_t __vsyscall(1) vtime(time_t *t)
        return __xtime.tv_sec;
 }
 
-static long __vsyscall(2) venosys_0(void)
+long __vsyscall(2) venosys_0(void)
 {
        return -ENOSYS;
 }
 
-static long __vsyscall(3) venosys_1(void)
+long __vsyscall(3) venosys_1(void)
 {
        return -ENOSYS;
 }
index bd556c8042488a470f7b428e339061738b7fd8c5..dfa358b05c893e17127178fcd8504ebfc0ce556d 100644 (file)
@@ -7,7 +7,7 @@
 #define FIX_ALIGNMENT 1
                
        #include <asm/current.h>
-       #include <asm/offset.h>
+       #include <asm/asm-offsets.h>
        #include <asm/thread_info.h>
        #include <asm/cpufeature.h>
 
index f80bafee8669fbcb0420d6e5173ea1f79e863082..3844d5e885a4deafcc035334e7d86b48351daf52 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/errno.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
        .text
index 5828b8191667da13f3295034a685f474746ce3b2..7f5593974e2d0b101c35091b267792943fbe9451 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/errno.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
        .text
index 816732d8858c3195c7b6d78419b2b0b537de3f10..b75b872ec154f8e004fc04a29375eb97f7f468bb 100644 (file)
@@ -221,12 +221,13 @@ int unhandled_signal(struct task_struct *tsk, int sig)
 static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
                                 unsigned long error_code)
 {
-       oops_begin();
+       unsigned long flags = oops_begin();
+
        printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
               current->comm, address);
        dump_pagetable(address);
        __die("Bad pagetable", regs, error_code);
-       oops_end();
+       oops_end(flags);
        do_exit(SIGKILL);
 }
 
@@ -304,6 +305,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        unsigned long address;
        const struct exception_table_entry *fixup;
        int write;
+       unsigned long flags;
        siginfo_t info;
 
 #ifdef CONFIG_CHECKING
@@ -521,7 +523,7 @@ no_context:
  * terminate things with extreme prejudice.
  */
 
-       oops_begin(); 
+       flags = oops_begin();
 
        if (address < PAGE_SIZE)
                printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
@@ -534,7 +536,7 @@ no_context:
        __die("Oops", regs, error_code);
        /* Executive summary in case the body of the oops scrolled away */
        printk(KERN_EMERG "CR2: %016lx\n", address);
-       oops_end(); 
+       oops_end(flags);
        do_exit(SIGKILL);
 
 /*
index aa4a5189ecee2640503d053bf6c79b233aa99f99..e60a1a848de8f622ce87bd7616b7c32b0dea6e0e 100644 (file)
@@ -57,31 +57,31 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 void show_mem(void)
 {
-       int i, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
+       long i, total = 0, reserved = 0;
+       long shared = 0, cached = 0;
        pg_data_t *pgdat;
        struct page *page;
 
-       printk("Mem-info:\n");
+       printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 
        for_each_pgdat(pgdat) {
                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
                        page = pfn_to_page(pgdat->node_start_pfn + i);
                        total++;
-                       if (PageReserved(page))
-                       reserved++;
-                       else if (PageSwapCache(page))
-                       cached++;
-                       else if (page_count(page))
-                               shared += page_count(page) - 1;
+                       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 reserved pages\n",reserved);
-       printk("%d pages shared\n",shared);
-       printk("%d pages swap cached\n",cached);
+       printk(KERN_INFO "%lu pages of RAM\n", total);
+       printk(KERN_INFO "%lu reserved pages\n",reserved);
+       printk(KERN_INFO "%lu pages shared\n",shared);
+       printk(KERN_INFO "%lu pages swap cached\n",cached);
 }
 
 /* References to section boundaries */
@@ -381,41 +381,14 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
        __flush_tlb_all();
 } 
 
-static inline int page_is_ram (unsigned long pagenr)
-{
-       int i;
-
-       for (i = 0; i < e820.nr_map; i++) {
-               unsigned long addr, end;
-
-               if (e820.map[i].type != E820_RAM)       /* not usable memory */
-                       continue;
-               /*
-                *      !!!FIXME!!! Some BIOSen report areas as RAM that
-                *      are not. Notably the 640->1Mb area. We need a sanity
-                *      check here.
-                */
-               addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
-               end = (e820.map[i].addr+e820.map[i].size) >> PAGE_SHIFT;
-               if  ((pagenr >= addr) && (pagenr < end))
-                       return 1;
-       }
-       return 0;
-}
-
-extern int swiotlb_force;
-
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
                         kcore_vsyscall;
 
 void __init mem_init(void)
 {
-       int codesize, reservedpages, datasize, initsize;
-       int tmp;
+       long codesize, reservedpages, datasize, initsize;
 
 #ifdef CONFIG_SWIOTLB
-       if (swiotlb_force)
-               swiotlb = 1;
        if (!iommu_aperture &&
            (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
               swiotlb = 1;
@@ -436,25 +409,11 @@ void __init mem_init(void)
 
        /* this will put all low memory onto the freelists */
 #ifdef CONFIG_NUMA
-       totalram_pages += numa_free_all_bootmem();
-       tmp = 0;
-       /* should count reserved pages here for all nodes */ 
+       totalram_pages = numa_free_all_bootmem();
 #else
-
-#ifdef CONFIG_FLATMEM
-       max_mapnr = end_pfn;
-       if (!mem_map) BUG();
-#endif
-
-       totalram_pages += free_all_bootmem();
-
-       for (tmp = 0; tmp < end_pfn; tmp++)
-               /*
-                * Only count reserved RAM pages
-                */
-               if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
-                       reservedpages++;
+       totalram_pages = free_all_bootmem();
 #endif
+       reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
 
        after_bootmem = 1;
 
@@ -471,7 +430,7 @@ void __init mem_init(void)
        kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, 
                                 VSYSCALL_END - VSYSCALL_START);
 
-       printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+       printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                end_pfn << (PAGE_SHIFT-10),
                codesize >> 10,
index ec35747aacd764b0aedf1824e604b704e5a164e9..65417b040c1bffd171f0ce46d590a57e174c742b 100644 (file)
@@ -45,10 +45,12 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        unsigned long prevbase;
        struct node nodes[8];
        int nodeid, i, nb; 
+       unsigned char nodeids[8];
        int found = 0;
        u32 reg;
        unsigned numnodes;
        nodemask_t nodes_parsed;
+       unsigned dualcore = 0;
 
        nodes_clear(nodes_parsed);
 
@@ -67,11 +69,15 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        prevbase = 0;
        for (i = 0; i < 8; i++) { 
                unsigned long base,limit; 
-
+               u32 nodeid;
+               
+               /* Undefined before E stepping, but hopefully 0 */
+               dualcore |= ((read_pci_config(0, nb, 3, 0xe8) >> 12) & 3) == 1;
                base = read_pci_config(0, nb, 1, 0x40 + i*8);
                limit = read_pci_config(0, nb, 1, 0x44 + i*8);
 
                nodeid = limit & 7; 
+               nodeids[i] = nodeid;
                if ((base & 3) == 0) { 
                        if (i < numnodes)
                                printk("Skipping disabled node %d\n", i); 
@@ -157,8 +163,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 
        for (i = 0; i < 8; i++) {
                if (nodes[i].start != nodes[i].end) { 
-                       /* assume 1:1 NODE:CPU */
-                       cpu_to_node[i] = i; 
+                       nodeid = nodeids[i];
+                       apicid_to_node[nodeid << dualcore] = i;
+                       apicid_to_node[(nodeid << dualcore) + dualcore] = i;
                        setup_node_bootmem(i, nodes[i].start, nodes[i].end); 
                } 
        }
index 04f7a33e144c4bbbd05befd65d6c396184e6e75d..80a49d9bd8a77941a89794b32eba75e0cc2490aa 100644 (file)
@@ -28,8 +28,13 @@ bootmem_data_t plat_node_bdata[MAX_NUMNODES];
 int memnode_shift;
 u8  memnodemap[NODEMAPSIZE];
 
-unsigned char cpu_to_node[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
-cpumask_t     node_to_cpumask[MAX_NUMNODES] __read_mostly;
+unsigned char cpu_to_node[NR_CPUS] __read_mostly = {
+       [0 ... NR_CPUS-1] = NUMA_NO_NODE
+};
+unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+       [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly;
 
 int numa_off __initdata;
 
index 8e3d097a9ddddc5ef1c179cd24ae28a6d7902163..4b2e844c15a75707de27bccac2dcccd750db480c 100644 (file)
 
 static struct acpi_table_slit *acpi_slit;
 
-/* Internal processor count */
-static unsigned int __initdata num_processors = 0;
-
 static nodemask_t nodes_parsed __initdata;
 static nodemask_t nodes_found __initdata;
 static struct node nodes[MAX_NUMNODES] __initdata;
 static __u8  pxm2node[256] = { [0 ... 255] = 0xff };
 
+static int node_to_pxm(int n);
+
+int pxm_to_node(int pxm)
+{
+       if ((unsigned)pxm >= 256)
+               return 0;
+       return pxm2node[pxm];
+}
+
 static __init int setup_node(int pxm)
 {
        unsigned node = pxm2node[pxm];
@@ -44,14 +50,14 @@ static __init int setup_node(int pxm)
 static __init int conflicting_nodes(unsigned long start, unsigned long end)
 {
        int i;
-       for_each_online_node(i) {
+       for_each_node_mask(i, nodes_parsed) {
                struct node *nd = &nodes[i];
                if (nd->start == nd->end)
                        continue;
                if (nd->end > start && nd->start < end)
-                       return 1;
+                       return i;
                if (nd->end == end && nd->start == start)
-                       return 1;
+                       return i;
        }
        return -1;
 }
@@ -75,8 +81,11 @@ static __init void cutoff_node(int i, unsigned long start, unsigned long end)
 
 static __init void bad_srat(void)
 {
+       int i;
        printk(KERN_ERR "SRAT: SRAT not used.\n");
        acpi_numa = -1;
+       for (i = 0; i < MAX_LOCAL_APIC; i++)
+               apicid_to_node[i] = NUMA_NO_NODE;
 }
 
 static __init inline int srat_disabled(void)
@@ -104,18 +113,10 @@ acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa)
                bad_srat();
                return;
        }
-       if (num_processors >= NR_CPUS) {
-               printk(KERN_ERR "SRAT: Processor #%d (lapic %u) INVALID. (Max ID: %d).\n",
-                       num_processors, pa->apic_id, NR_CPUS);
-               bad_srat();
-               return;
-       }
-       cpu_to_node[num_processors] = node;
+       apicid_to_node[pa->apic_id] = node;
        acpi_numa = 1;
-       printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> CPU %u -> Node %u\n",
-              pxm, pa->apic_id, num_processors, node);
-
-       num_processors++;
+       printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n",
+              pxm, pa->apic_id, node);
 }
 
 /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */
@@ -143,10 +144,15 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
                printk(KERN_INFO "SRAT: hot plug zone found %lx - %lx \n",
                                start, end);
        i = conflicting_nodes(start, end);
-       if (i >= 0) {
+       if (i == node) {
+               printk(KERN_WARNING
+               "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
+                       pxm, start, end, nodes[i].start, nodes[i].end);
+       } else if (i >= 0) {
                printk(KERN_ERR
-                      "SRAT: pxm %d overlap %lx-%lx with node %d(%Lx-%Lx)\n",
-                      pxm, start, end, i, nodes[i].start, nodes[i].end);
+                      "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
+                      pxm, start, end, node_to_pxm(i),
+                       nodes[i].start, nodes[i].end);
                bad_srat();
                return;
        }
@@ -174,6 +180,14 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
        int i;
        if (acpi_numa <= 0)
                return -1;
+
+       /* First clean up the node list */
+       for_each_node_mask(i, nodes_parsed) {
+               cutoff_node(i, start, end);
+               if (nodes[i].start == nodes[i].end)
+                       node_clear(i, nodes_parsed);
+       }
+
        memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
        if (memnode_shift < 0) {
                printk(KERN_ERR
@@ -181,16 +195,10 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
                bad_srat();
                return -1;
        }
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               if (!node_isset(i, nodes_parsed))
-                       continue;
-               cutoff_node(i, start, end);
-               if (nodes[i].start == nodes[i].end) { 
-                       node_clear(i, nodes_parsed);
-                       continue;
-               }
+
+       /* Finally register nodes */
+       for_each_node_mask(i, nodes_parsed)
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-       }
        for (i = 0; i < NR_CPUS; i++) { 
                if (cpu_to_node[i] == NUMA_NO_NODE)
                        continue;
@@ -201,7 +209,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
        return 0;
 }
 
-int node_to_pxm(int n)
+static int node_to_pxm(int n)
 {
        int i;
        if (pxm2node[n] == n)
index d80c323669e0c5e741a33f8c5700b2c8b8784007..3acf60ded2a0b54144a72b5b0faf5f8bc2c00933 100644 (file)
@@ -58,10 +58,16 @@ fill_mp_bus_to_cpumask(void)
                                for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
                                     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
                                     j++) { 
-                                       int node = NODE_ID(nid);
+                                       struct pci_bus *bus;
+                                       long node = NODE_ID(nid);
+                                       /* Algorithm a bit dumb, but
+                                          it shouldn't matter here */
+                                       bus = pci_find_bus(0, j);
+                                       if (!bus)
+                                               continue;
                                        if (!node_online(node))
                                                node = 0;
-                                       pci_bus_to_node[j] = node;
+                                       bus->sysdata = (void *)node;
                                }               
                        }
                }
index 657e88aa09022ba67df0fcc8dca7d20e44ecef53..a0838c4a94e4c032d9d6024fb0eaed96b0d3dab3 100644 (file)
@@ -111,13 +111,6 @@ static int __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return 0;
 
-       /* Kludge for now. Don't use mmconfig on AMD systems because
-          those have some busses where mmconfig doesn't work,
-          and we don't parse ACPI MCFG well enough to handle that. 
-          Remove when proper handling is added. */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
-               return 0; 
-
        /* RED-PEN i386 doesn't do _nocache right now */
        pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {
index 27847e4ffcbfa5212a7ca87fc104941686c5473d..98fac8489aede5b8e4b7648258036e54d5dc12b2 100644 (file)
@@ -66,13 +66,7 @@ boot         := arch/xtensa/boot
 
 archinc                := include/asm-xtensa
 
-arch/xtensa/kernel/asm-offsets.s: \
-       arch/xtensa/kernel/asm-offsets.c $(archinc)/.platform
-
-include/asm-xtensa/offsets.h: arch/xtensa/kernel/asm-offsets.s
-       $(call filechk,gen-asm-offsets)
-
-prepare: $(archinc)/.platform $(archinc)/offsets.h
+archprepare: $(archinc)/.platform
 
 # Update machine cpu and platform symlinks if something which affects
 # them changed.
@@ -94,7 +88,7 @@ bzImage : zImage
 zImage zImage.initrd: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $@
 
-CLEAN_FILES    += arch/xtensa/vmlinux.lds $(archinc)/offset.h \
+CLEAN_FILES    += arch/xtensa/vmlinux.lds                      \
                   $(archinc)/platform $(archinc)/xtensa/config \
                   $(archinc)/.platform
 
index 74b1e90ef08c233513889d8a5edba4b277c85b74..a4956578a24df35269c72e018e4fee936253d4ec 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/ptrace.h>
 #include <asm/ptrace.h>
 #include <asm/current.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/page.h>
index c64a01f71de6929e12020e75649afd3e18b36f8f..5c018c503dfa0d465d93a3f322a62a18159fd46c 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 #include <linux/linkage.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include <asm/uaccess.h>
index 4099703b14bedd837aa42116e68269a480fe52b9..c83bb0d41787b0789f2a4717dd810958b1e43848 100644 (file)
@@ -43,7 +43,7 @@
 #include <asm/mmu.h>
 #include <asm/irq.h>
 #include <asm/atomic.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/coprocessor.h>
 
 extern void ret_from_fork(void);
index 81808f0c67420bd1e462e0f95aa0853f260409ab..0e74397bfa2bd8168660ca29c7ae439cd23fcee8 100644 (file)
@@ -46,7 +46,7 @@
 #include <asm/ptrace.h>
 #include <asm/ptrace.h>
 #include <asm/current.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/page.h>
index c0a37d98b4f3d3c3c485de77ac2391295089852b..048542341204e716bc24e721914a240cf781426e 100644 (file)
@@ -376,19 +376,15 @@ static void do_fd_request(request_queue_t *);
 
 /************************* End of Prototypes **************************/
 
-static struct timer_list motor_off_timer =
-       TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
+static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
 
 #ifdef TRACKBUFFER
-static struct timer_list readtrack_timer =
-       TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
+static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
 #endif
 
-static struct timer_list timeout_timer =
-       TIMER_INITIALIZER(fd_times_out, 0, 0);
+static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
 
-static struct timer_list fd_timer =
-       TIMER_INITIALIZER(check_change, 0, 0);
+static DEFINE_TIMER(fd_timer, check_change, 0, 0);
 
 /* DAG: Haven't got a clue what this is? */
 int stdma_islocked(void)
index 7249ba2b7a2740affaee5ba54d82ca4d27c2cc1c..aee50b453265905d22442992afc6f4701177a98e 100644 (file)
@@ -23,7 +23,6 @@ u8 sleep_states[ACPI_S_STATE_COUNT];
 
 static struct pm_ops acpi_pm_ops;
 
-extern void do_suspend_lowlevel_s4bios(void);
 extern void do_suspend_lowlevel(void);
 
 static u32 acpi_suspend_states[] = {
@@ -98,8 +97,6 @@ static int acpi_pm_enter(suspend_state_t pm_state)
        case PM_SUSPEND_DISK:
                if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM)
                        status = acpi_enter_sleep_state(acpi_state);
-               else
-                       do_suspend_lowlevel_s4bios();
                break;
        case PM_SUSPEND_MAX:
                acpi_power_off();
@@ -206,11 +203,6 @@ static int __init acpi_sleep_init(void)
                        printk(" S%d", i);
                }
                if (i == ACPI_STATE_S4) {
-                       if (acpi_gbl_FACS->S4bios_f) {
-                               sleep_states[i] = 1;
-                               printk(" S4bios");
-                               acpi_pm_ops.pm_disk_mode = PM_DISK_FIRMWARE;
-                       }
                        if (sleep_states[i])
                                acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
                }
index a5f947de879bc62a52ade449c729cf5ffe5b69c5..af7935a95bcc821efea2c4236817e4c5cf0286be 100644 (file)
@@ -21,9 +21,7 @@ int acpi_sleep_prepare(u32 acpi_state)
 {
 #ifdef CONFIG_ACPI_SLEEP
        /* do we have a wakeup address for S2 and S3? */
-       /* Here, we support only S4BIOS, those we set the wakeup address */
-       /* S4OS is only supported for now via swsusp.. */
-       if (acpi_state == ACPI_STATE_S3 || acpi_state == ACPI_STATE_S4) {
+       if (acpi_state == ACPI_STATE_S3) {
                if (!acpi_wakeup_address) {
                        return -EFAULT;
                }
index 09a603f3523ec148df72d54d629ef4712fdbe8c6..4696a85a98b92b34c2789e52fae6a6122039b447 100644 (file)
@@ -25,8 +25,6 @@ static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
        for (i = 0; i <= ACPI_STATE_S5; i++) {
                if (sleep_states[i]) {
                        seq_printf(seq, "S%d ", i);
-                       if (i == ACPI_STATE_S4 && acpi_gbl_FACS->S4bios_f)
-                               seq_printf(seq, "S4bios ");
                }
        }
 
index b8c260ed4b27aeef6ff45a17c14b2e7d21d037c5..0aabfc2a59d9e42a574673772a34765dc64f5ab6 100644 (file)
@@ -50,10 +50,8 @@ static void idt77105_stats_timer_func(unsigned long);
 static void idt77105_restart_timer_func(unsigned long);
 
 
-static struct timer_list stats_timer =
-    TIMER_INITIALIZER(idt77105_stats_timer_func, 0, 0);
-static struct timer_list restart_timer =
-    TIMER_INITIALIZER(idt77105_restart_timer_func, 0, 0);
+static DEFINE_TIMER(stats_timer, idt77105_stats_timer_func, 0, 0);
+static DEFINE_TIMER(restart_timer, idt77105_restart_timer_func, 0, 0);
 static int start_timer = 1;
 static struct idt77105_priv *idt77105_all = NULL;
 
index a43575acb2c1d16bba33a68e725650c1eae28660..2e2e50e1167a3b59f31a809bfbea43992b19b478 100644 (file)
@@ -79,7 +79,7 @@ static IADEV *ia_dev[8];
 static struct atm_dev *_ia_dev[8];
 static int iadev_count;
 static void ia_led_timer(unsigned long arg);
-static struct timer_list ia_timer = TIMER_INITIALIZER(ia_led_timer, 0, 0);
+static DEFINE_TIMER(ia_timer, ia_led_timer, 0, 0);
 static int IA_TX_BUF = DFL_TX_BUFFERS, IA_TX_BUF_SZ = DFL_TX_BUF_SZ;
 static int IA_RX_BUF = DFL_RX_BUFFERS, IA_RX_BUF_SZ = DFL_RX_BUF_SZ;
 static uint IADebugFlag = /* IF_IADBG_ERR | IF_IADBG_CBR| IF_IADBG_INIT_ADAPTER
index c4aebf2f522d724abfbb8e1c5538ac8441322bbd..60a7ef6a201b879ecedafe996c36c730259d4ba6 100644 (file)
@@ -262,7 +262,8 @@ dma_pool_destroy (struct dma_pool *pool)
  * If such a memory block can't be allocated, null is returned.
  */
 void *
-dma_pool_alloc (struct dma_pool *pool, int mem_flags, dma_addr_t *handle)
+dma_pool_alloc (struct dma_pool *pool, unsigned int __nocast mem_flags,
+               dma_addr_t *handle)
 {
        unsigned long           flags;
        struct dma_page         *page;
index ce933de4808494445996ee5c161f8dbca576222e..0e1f34fef0c838e26b49e18706dd4c30e8f6bc8b 100644 (file)
@@ -371,7 +371,7 @@ static int acsi_revalidate (struct gendisk *disk);
 /************************* End of Prototypes **************************/
 
 
-struct timer_list acsi_timer = TIMER_INITIALIZER(acsi_times_out, 0, 0);
+DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
 
 
 #ifdef CONFIG_ATARI_SLM
index e3be8c31a74ccb5dbc8ef1005682239cd5d2d667..a5c1c8e871ec38aacc9abcbbe15a211ab3269b85 100644 (file)
@@ -268,7 +268,7 @@ static int slm_get_pagesize( int device, int *w, int *h );
 /************************* End of Prototypes **************************/
 
 
-static struct timer_list slm_timer = TIMER_INITIALIZER(slm_test_ready, 0, 0);
+static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0);
 
 static struct file_operations slm_fops = {
        .owner =        THIS_MODULE,
index db05a5a99f354537ce3bd69de48e8a84a3cd14dd..22bda05fc693f454e801ce902ec248a2416572bd 100644 (file)
@@ -371,16 +371,10 @@ static int floppy_release( struct inode * inode, struct file * filp );
 
 /************************* End of Prototypes **************************/
 
-static struct timer_list motor_off_timer =
-       TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
-static struct timer_list readtrack_timer =
-       TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
-
-static struct timer_list timeout_timer =
-       TIMER_INITIALIZER(fd_times_out, 0, 0);
-
-static struct timer_list fd_timer =
-       TIMER_INITIALIZER(check_change, 0, 0);
+static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
+static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
+static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
+static DEFINE_TIMER(fd_timer, check_change, 0, 0);
        
 static inline void start_motor_off_timer(void)
 {
index 418b1469d75d116b1f029e4ae5bc44ed1dd768a2..28f2c177a54167a0ce7d3bd9e3f1dbe7ac1d7995 100644 (file)
@@ -1713,10 +1713,9 @@ static unsigned long pollcomplete(int ctlr)
 
        for (i = 20 * HZ; i > 0; i--) {
                done = hba[ctlr]->access.command_completed(hba[ctlr]);
-               if (done == FIFO_EMPTY) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(1);
-               } else
+               if (done == FIFO_EMPTY)
+                       schedule_timeout_uninterruptible(1);
+               else
                        return (done);
        }
        /* Invalid address to tell caller we ran out of time */
index 30c0903c7cddfdd46dbdd0de9c8e999c1ed7f349..cd056e7e64ec15d5cf81f16068623e29e07ad187 100644 (file)
@@ -2260,6 +2260,8 @@ static void cfq_put_cfqd(struct cfq_data *cfqd)
        if (!atomic_dec_and_test(&cfqd->ref))
                return;
 
+       blk_put_queue(q);
+
        cfq_shutdown_timer_wq(cfqd);
        q->elevator->elevator_data = NULL;
 
@@ -2316,6 +2318,7 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e)
        e->elevator_data = cfqd;
 
        cfqd->queue = q;
+       atomic_inc(&q->refcnt);
 
        cfqd->max_queued = q->nr_requests / 4;
        q->nr_batching = cfq_queued;
index 24594c57c3230e5a095eb10ddb282137ed9161ba..52a3ae5289a09a7af79081df5de2ec7e4c40ff26 100644 (file)
@@ -512,7 +512,10 @@ static int deadline_dispatch_requests(struct deadline_data *dd)
        /*
         * batches are currently reads XOR writes
         */
-       drq = dd->next_drq[WRITE] ? : dd->next_drq[READ];
+       if (dd->next_drq[WRITE])
+               drq = dd->next_drq[WRITE];
+       else
+               drq = dd->next_drq[READ];
 
        if (drq) {
                /* we have a "next request" */
index 888dad5eef34994fad9718223f31a1fc8513866f..00895477155e69aaac17792f253681d0e4c0a2d0 100644 (file)
@@ -628,7 +628,7 @@ static inline void debugt(const char *message) { }
 #endif /* DEBUGT */
 
 typedef void (*timeout_fn) (unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
+static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
 
 static const char *timeout_message;
 
@@ -1012,7 +1012,7 @@ static void schedule_bh(void (*handler) (void))
        schedule_work(&floppy_work);
 }
 
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(fd_timer, NULL, 0, 0);
 
 static void cancel_activity(void)
 {
index 7289f67e9568771fb703435917814868bf482757..ac5ba462710b2f0af37b37032804aa238bbdf2b8 100644 (file)
@@ -516,8 +516,7 @@ static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
 
 static void pcd_sleep(int cs)
 {
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(cs);
+       schedule_timeout_interruptible(cs);
 }
 
 static int pcd_reset(struct pcd_unit *cd)
index 060b1f2a91ddcec82c36d70d3ea383080b58033e..711d2f314ac32736c01fcdd63647d18f2d0eecb7 100644 (file)
@@ -507,8 +507,7 @@ static void pf_eject(struct pf_unit *pf)
 
 static void pf_sleep(int cs)
 {
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(cs);
+       schedule_timeout_interruptible(cs);
 }
 
 /* the ATAPI standard actually specifies the contents of all 7 registers
index 84d8e291ed964aaafb537790dc2fd00f1b781263..b3982395f22b4d56fcc0de0f1f555ee699b2447f 100644 (file)
@@ -276,8 +276,7 @@ static inline u8 DRIVE(struct pg *dev)
 
 static void pg_sleep(int cs)
 {
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(cs);
+       schedule_timeout_interruptible(cs);
 }
 
 static int pg_wait(struct pg *dev, int go, int stop, unsigned long tmo, char *msg)
index 5fe8ee86f095bb82a9691fd5792f8411a4797555..d8d35233cf495df4fd84fbdecd9cb65710137993 100644 (file)
@@ -383,8 +383,7 @@ static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *
 
 static void pt_sleep(int cs)
 {
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(cs);
+       schedule_timeout_interruptible(cs);
 }
 
 static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg)
index 29548784cb7b1ab734c65e68897867a7c992523e..29d1518be72a16ba980e71eb829a671208e1fbdf 100644 (file)
@@ -99,8 +99,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
 static int no_int_yet;
 static int ps2esdi_drives;
 static u_short io_base;
-static struct timer_list esdi_timer =
-               TIMER_INITIALIZER(ps2esdi_reset_timer, 0, 0);
+static DEFINE_TIMER(esdi_timer, ps2esdi_reset_timer, 0, 0);
 static int reset_status;
 static int ps2esdi_slot = -1;
 static int tp720esdi = 0;      /* Is it Integrated ESDI of ThinkPad-720? */
index e5f7494c00eed322d946269a568acf9240632c55..e425ad3eebba80618be8c56f6282f9ed99bad740 100644 (file)
@@ -834,8 +834,7 @@ static int fd_eject(struct floppy_state *fs)
                        break;
                }
                swim3_select(fs, RELAX);
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
                if (swim3_readbit(fs, DISK_IN) == 0)
                        break;
        }
@@ -906,8 +905,7 @@ static int floppy_open(struct inode *inode, struct file *filp)
                                break;
                        }
                        swim3_select(fs, RELAX);
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(1);
+                       schedule_timeout_interruptible(1);
                }
                if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0
                                 || swim3_readbit(fs, DISK_IN) == 0))
@@ -992,8 +990,7 @@ static int floppy_revalidate(struct gendisk *disk)
                if (signal_pending(current))
                        break;
                swim3_select(fs, RELAX);
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
        }
        ret = swim3_readbit(fs, SEEK_COMPLETE) == 0
                || swim3_readbit(fs, DISK_IN) == 0;
index a1283f6dc0189e1ee0d3d7b0622ea875f2333b5d..89e3c2f8b77681bacd376ba480732d4e84b97b9d 100644 (file)
@@ -338,8 +338,7 @@ static int swimiop_eject(struct floppy_state *fs)
                        err = -EINTR;
                        break;
                }
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(1);
+               schedule_timeout_interruptible(1);
        }
        release_drive(fs);
        return cmd->error;
index 0c4c121d2e7962bf798958ad2cee2df0e907527c..0f48301342da4e2e0a13a23bed85821e06efb79b 100644 (file)
@@ -34,6 +34,7 @@
  *                      - set initialised bit then.
  */
 
+//#define DEBUG /* uncomment if you want debugging info (pr_debug) */
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#define PRINTK(x...) do {} while (0)
-#define dprintk(x...) do {} while (0)
-/*#define dprintk(x...) printk(x) */
-
 #define MM_MAXCARDS 4
 #define MM_RAHEAD 2      /* two sectors */
 #define MM_BLKSIZE 1024  /* 1k blocks */
@@ -299,7 +296,7 @@ static void mm_start_io(struct cardinfo *card)
 
        /* make the last descriptor end the chain */
        page = &card->mm_pages[card->Active];
-       PRINTK("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
+       pr_debug("start_io: %d %d->%d\n", card->Active, page->headcnt, page->cnt-1);
        desc = &page->desc[page->cnt-1];
 
        desc->control_bits |= cpu_to_le32(DMASCR_CHAIN_COMP_EN);
@@ -532,7 +529,7 @@ static void process_page(unsigned long data)
                activate(card);
        } else {
                /* haven't finished with this one yet */
-               PRINTK("do some more\n");
+               pr_debug("do some more\n");
                mm_start_io(card);
        }
  out_unlock:
@@ -555,7 +552,7 @@ static void process_page(unsigned long data)
 static int mm_make_request(request_queue_t *q, struct bio *bio)
 {
        struct cardinfo *card = q->queuedata;
-       PRINTK("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
+       pr_debug("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
 
        bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/
        spin_lock_irq(&card->lock);
index 1676033da6c6f359b060b57cfe4a46bae0d63772..68b6d7b154cf88057b138d72a58b74d93409c23f 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/wait.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -62,7 +63,7 @@ static int xd[5] = { -1,-1,-1,-1, };
 
 #define XD_DONT_USE_DMA                0  /* Initial value. may be overriden using
                                      "nodma" module option */
-#define XD_INIT_DISK_DELAY     (30*HZ/1000)  /* 30 ms delay during disk initialization */
+#define XD_INIT_DISK_DELAY     (30)  /* 30 ms delay during disk initialization */
 
 /* Above may need to be increased if a problem with the 2nd drive detection
    (ST11M controller) or resetting a controller (WD) appears */
@@ -529,10 +530,8 @@ static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long t
        int success;
 
        xdc_busy = 1;
-       while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry))
+               schedule_timeout_uninterruptible(1);
        xdc_busy = 0;
        return (success);
 }
@@ -633,14 +632,12 @@ static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
        for (i = 0; i < XD_MAXDRIVES; i++) {
                xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
                if (!xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT*8)) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(XD_INIT_DISK_DELAY);
+                       msleep_interruptible(XD_INIT_DISK_DELAY);
 
                        init_drive(count);
                        count++;
 
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(XD_INIT_DISK_DELAY);
+                       msleep_interruptible(XD_INIT_DISK_DELAY);
                }
        }
        return (count);
@@ -761,8 +758,7 @@ static void __init xd_wd_init_controller (unsigned int address)
 
        outb(0,XD_RESET);               /* reset the controller */
 
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(XD_INIT_DISK_DELAY);
+       msleep(XD_INIT_DISK_DELAY);
 }
 
 static void __init xd_wd_init_drive (u_char drive)
@@ -936,8 +932,7 @@ If you need non-standard settings use the xd=... command */
        xd_maxsectors = 0x01;
        outb(0,XD_RESET);               /* reset the controller */
 
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(XD_INIT_DISK_DELAY);
+       msleep(XD_INIT_DISK_DELAY);
 }
 
 static void __init xd_xebec_init_drive (u_char drive)
index 007f6a6624392c6427601306dddebbda745d60e9..bb5e8d665a2a3ce8bd41fbd647bd06eeec772541 100644 (file)
@@ -296,7 +296,7 @@ z2_open( struct inode *inode, struct file *filp )
     return 0;
 
 err_out_kfree:
-    kfree( z2ram_map );
+    kfree(z2ram_map);
 err_out:
     return rc;
 }
index 43bf1e5dc38a4dfb0a6a0285b9fe041875bc21fa..ce4a1ce59d6a2369ee22bbebeca2f4bc62346659 100644 (file)
@@ -297,7 +297,7 @@ static char azt_auto_eject = AZT_AUTO_EJECT;
 
 static int AztTimeout, AztTries;
 static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static struct timer_list delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(delay_timer, NULL, 0, 0);
 
 static struct azt_DiskInfo DiskInfo;
 static struct azt_Toc Toc[MAX_TRACKS];
index 7eac10e63b2356d73e360b3cdb113b45019d77d7..ad5464ab99bce830fc22984ff1cf77ac176c51d2 100644 (file)
@@ -146,7 +146,7 @@ static int AudioStart_f;
 static int AudioEnd_m;
 static int AudioEnd_f;
 
-static struct timer_list gscd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
 static DEFINE_SPINLOCK(gscd_lock);
 static struct request_queue *gscd_queue;
 
index 351a01dd503a3ceea3073f0c6dd31acd82e4c70f..0b0eab4f40fa989dd9c215b089282bc8d8fa106a 100644 (file)
@@ -264,7 +264,7 @@ static inline int flag_low(int flag, unsigned long timeout)
 static int sleep_timeout;      /* max # of ticks to sleep */
 static DECLARE_WAIT_QUEUE_HEAD(waitq);
 static void sleep_timer(unsigned long data);
-static struct timer_list delay_timer = TIMER_INITIALIZER(sleep_timer, 0, 0);
+static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
 static DEFINE_SPINLOCK(optcd_lock);
 static struct request_queue *opt_queue;
 
index 452d34675159cd4dbfc6894af5cf7f2b8de19712..466e9c2974bdd917e7840daa8f075e8f7bda7cb9 100644 (file)
@@ -742,13 +742,10 @@ static struct sbpcd_drive *current_drive = D_S;
 unsigned long cli_sti; /* for saving the processor flags */
 #endif
 /*==========================================================================*/
-static struct timer_list delay_timer =
-               TIMER_INITIALIZER(mark_timeout_delay, 0, 0);
-static struct timer_list data_timer =
-               TIMER_INITIALIZER(mark_timeout_data, 0, 0);
+static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
+static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
 #if 0
-static struct timer_list audio_timer =
-               TIMER_INITIALIZER(mark_timeout_audio, 0, 0);
+static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
 #endif
 /*==========================================================================*/
 /*
@@ -830,8 +827,7 @@ static void mark_timeout_audio(u_long i)
 static void sbp_sleep(u_int time)
 {
        sti();
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(time);
+       schedule_timeout_interruptible(time);
        sti();
 }
 /*==========================================================================*/
@@ -4219,7 +4215,8 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
                
        case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
                msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
-               if (current_drive->sbp_audsiz>0) vfree(current_drive->aud_buf);
+               if (current_drive->sbp_audsiz>0)
+                       vfree(current_drive->aud_buf);
                current_drive->aud_buf=NULL;
                current_drive->sbp_audsiz=arg;
                
@@ -5913,7 +5910,8 @@ static void sbpcd_exit(void)
                put_disk(D_S[j].disk);
                devfs_remove("sbp/c0t%d", j);
                vfree(D_S[j].sbp_buf);
-               if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
+               if (D_S[j].sbp_audsiz>0)
+                       vfree(D_S[j].aud_buf);
                if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
                {
                        msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
index 4e7a342ec36ffff10ac0871140317fd4db01d1ff..74b1cadbf161d2adc2f7d61933622bfb8f75bc5e 100644 (file)
@@ -151,7 +151,7 @@ static struct sjcd_stat statistic;
 /*
  * Timer.
  */
-static struct timer_list sjcd_delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
 
 #define SJCD_SET_TIMER( func, tmout )           \
     ( sjcd_delay_timer.expires = jiffies+tmout,         \
index 9f22e8f1f6c0182dbbbb9ecd5689d01235f53404..e6565992643260580cbbcaf7e5209a1744fd97f2 100644 (file)
@@ -1478,8 +1478,7 @@ static int __init sony535_init(void)
        /* look for the CD-ROM, follows the procedure in the DOS driver */
        inb(select_unit_reg);
        /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout((HZ+17)*40/18);
+       schedule_timeout_interruptible((HZ+17)*40/18);
        inb(result_reg);
 
        outb(0, read_status_reg);       /* does a reset? */
index 4d4e602fdc7e7cfa326000b84135583ed866296d..82b43c541c8dca52ad90c0ea6c6b984a50c455ee 100644 (file)
@@ -206,10 +206,9 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
                bridge->driver->cleanup();
        if (bridge->driver->free_gatt_table)
                bridge->driver->free_gatt_table(bridge);
-       if (bridge->key_list) {
-               vfree(bridge->key_list);
-               bridge->key_list = NULL;
-       }
+
+       vfree(bridge->key_list);
+       bridge->key_list = NULL;
 
        if (bridge->driver->agp_destroy_page &&
            bridge->driver->needs_scratch_page)
index 11f9ee5811242973f15bc0232d1e15fbee33373e..927a5bbe112c9d9eb175e6840f557d4348d159c2 100644 (file)
@@ -172,7 +172,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc,
 
 void cleanup_module(void)
 {
-       int i;
+       unsigned int i;
 
        misc_deregister(&ac_miscdev);
 
@@ -195,7 +195,7 @@ int __init applicom_init(void)
        int i, numisa = 0;
        struct pci_dev *dev = NULL;
        void __iomem *RamIO;
-       int boardno;
+       int boardno, ret;
 
        printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
 
@@ -294,7 +294,8 @@ int __init applicom_init(void)
        }
 
        if (!numisa)
-               printk(KERN_WARNING"ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem);
+               printk(KERN_WARNING "ac.o: No valid ISA Applicom boards found "
+                               "at mem 0x%lx\n", mem);
 
  fin:
        init_waitqueue_head(&FlagSleepRec);
@@ -304,7 +305,11 @@ int __init applicom_init(void)
        DeviceErrorCount = 0;
 
        if (numboards) {
-               misc_register(&ac_miscdev);
+               ret = misc_register(&ac_miscdev);
+               if (ret) {
+                       printk(KERN_WARNING "ac.o: Unable to register misc device\n");
+                       goto out;
+               }
                for (i = 0; i < MAX_BOARD; i++) {
                        int serial;
                        char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
@@ -337,6 +342,17 @@ int __init applicom_init(void)
 
        else
                return -ENXIO;
+
+out:
+       for (i = 0; i < MAX_BOARD; i++) {
+               if (!apbs[i].RamIO)
+                       continue;
+               if (apbs[i].irq)
+                       free_irq(apbs[i].irq, &dummy);
+               iounmap(apbs[i].RamIO);
+       }
+       pci_disable_device(dev);
+       return ret;
 }
 
 
index 6a5337bf09368dbd74f0202559e96bcff5067c9b..cf4c3648463dbf8d0cd28c9079be19e110dbefa4 100644 (file)
@@ -865,7 +865,7 @@ static void cyz_poll(unsigned long);
 static long cyz_polling_cycle = CZ_DEF_POLL;
 
 static int cyz_timeron = 0;
-static struct timer_list cyz_timerlist = TIMER_INITIALIZER(cyz_poll, 0, 0);
+static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
 
 #else /* CONFIG_CYZ_INTR */
 static void cyz_rx_restart(unsigned long);
index 1704a2a57048b85adda6bd799d488b053940ffc6..b2e0928e84288b6a392e7951fd3724649a54fd27 100644 (file)
@@ -387,10 +387,8 @@ int fdc_interrupt_wait(unsigned int time)
 
        set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&ftape_wait_intr, &wait);
-       while (!ft_interrupt_seen && timeout) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-        }
+       while (!ft_interrupt_seen && timeout)
+               timeout = schedule_timeout_interruptible(timeout);
 
        spin_lock_irq(&current->sighand->siglock);
        current->blocked = old_sigmask;
index 81d811edf3c58ec478dd73cb239fd2714bb84f32..a54bc93353af1d62d37ddf96af94d344e1bd60e4 100644 (file)
@@ -149,8 +149,7 @@ static unsigned long long hangcheck_tsc, hangcheck_tsc_margin;
 
 static void hangcheck_fire(unsigned long);
 
-static struct timer_list hangcheck_ticktock =
-               TIMER_INITIALIZER(hangcheck_fire, 0, 0);
+static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0);
 
 
 static void hangcheck_fire(unsigned long data)
index 5fe8461271fc35812222bd2b2e2f8e138d1ffc02..de0379b6d502cd4f2e512565bf6da5c04439780e 100644 (file)
@@ -100,14 +100,14 @@ static struct hpets *hpets;
 #endif
 
 #ifndef readq
-static unsigned long long __inline readq(void __iomem *addr)
+static inline unsigned long long readq(void __iomem *addr)
 {
        return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
 }
 #endif
 
 #ifndef writeq
-static void __inline writeq(unsigned long long v, void __iomem *addr)
+static inline void writeq(unsigned long long v, void __iomem *addr)
 {
        writel(v & 0xffffffff, addr);
        writel(v >> 32, addr + 4);
index 3480535a09c5f113af1ca110bb0fa37ae58c2206..6f673d2de0b1717439e5d908f4ce3e5cb4b85072 100644 (file)
@@ -513,10 +513,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
                        return ret ? : -EAGAIN;
 
                if(need_resched())
-               {
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(1);
-               }
+                       schedule_timeout_interruptible(1);
                else
                        udelay(200);    /* FIXME: We could poll for 250uS ?? */
 
index 82c5f30375acc816cd879dc0d083767cb9cd457a..ba85eb1b6ec75bfa56cd10b06b95cd9ff0186ee8 100644 (file)
@@ -655,8 +655,7 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
                        timeout--;   // So negative values == forever
                
                if (!in_interrupt()) {
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(1);    // short nap 
+                       schedule_timeout_interruptible(1);      // short nap
                } else {
                        // we cannot sched/sleep in interrrupt silly
                        return 0;   
@@ -1132,8 +1131,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user )
 
                                        ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
 
-                                       current->state = TASK_INTERRUPTIBLE;
-                                       schedule_timeout(2);
+                                       schedule_timeout_interruptible(2);
                                        if (signal_pending(current)) {
                                                break;
                                        }
index 066d7b5cb76d4e14227130659d846f24bd5db0f7..9e4e26aef94ea84d9824c0b61016f78f02bb1884 100644 (file)
@@ -254,7 +254,7 @@ static unsigned long bh_counter = 0;
  * selected, the board is serviced periodically to see if anything needs doing.
  */
 #define  POLL_TIMEOUT   (jiffies + 1)
-static struct timer_list PollTimer = TIMER_INITIALIZER(ip2_poll, 0, 0);
+static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
 static char  TimerOn;
 
 #ifdef IP2DEBUG_TRACE
index 883ac4352be49e4e1606e361d763a8503199a058..a09ff10806874d8fdf03b7c62d9fb8a8d0b0c916 100644 (file)
@@ -735,7 +735,8 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
        case COMPAT_IPMICTL_RECEIVE_MSG:
        case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
        {
-               struct ipmi_recv   *precv64, recv64;
+               struct ipmi_recv   __user *precv64;
+               struct ipmi_recv   recv64;
 
                if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
                        return -EFAULT;
@@ -748,7 +749,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
                                ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
                                 ? IPMICTL_RECEIVE_MSG
                                 : IPMICTL_RECEIVE_MSG_TRUNC),
-                               (long) precv64);
+                               (unsigned long) precv64);
                if (rc != 0)
                        return rc;
 
index 278f841049968c15867d25c34e2f17772d375829..b6e5cbfb09f81d897c1dd95079c4e9281dda4ba5 100644 (file)
@@ -1920,8 +1920,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
        for (;;)
        {
                if (smi_result == SI_SM_CALL_WITH_DELAY) {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(1);
+                       schedule_timeout_uninterruptible(1);
                        smi_result = smi_info->handlers->event(
                                smi_info->si_sm, 100);
                }
@@ -2256,10 +2255,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
 
        /* Wait for the timer to stop.  This avoids problems with race
           conditions removing the timer here. */
-       while (! new_smi->timer_stopped) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while (!new_smi->timer_stopped)
+               schedule_timeout_uninterruptible(1);
 
  out_err:
        if (new_smi->intf)
@@ -2379,17 +2376,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
 
        /* Wait for the timer to stop.  This avoids problems with race
           conditions removing the timer here. */
-       while (! to_clean->timer_stopped) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while (!to_clean->timer_stopped)
+               schedule_timeout_uninterruptible(1);
 
        /* Interrupts and timeouts are stopped, now make sure the
           interface is in a clean state. */
        while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                poll(to_clean);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_uninterruptible(1);
        }
 
        rv = ipmi_unregister_smi(to_clean->intf);
index e71aaae855adda775f9c296e6d91a333192d8110..2da64bf7469c6963e008e6215c610dae78dd3e3a 100644 (file)
@@ -1037,10 +1037,8 @@ static __exit void ipmi_unregister_watchdog(void)
        /* Wait to make sure the message makes it out.  The lower layer has
           pointers to our buffers, we want to make sure they are done before
           we release our memory. */
-       while (atomic_read(&set_timeout_tofree)) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while (atomic_read(&set_timeout_tofree))
+               schedule_timeout_uninterruptible(1);
 
        /* Disconnect from IPMI. */
        rv = ipmi_destroy_user(watchdog_user);
index 52a073eee201d697740fc9cad9530cc38f7e659a..9c19e5435a11faaa33df2a40a39ef2f7a4d06553 100644 (file)
@@ -780,7 +780,7 @@ static struct file_operations       stli_fsiomem = {
  *     much cheaper on host cpu than using interrupts. It turns out to
  *     not increase character latency by much either...
  */
-static struct timer_list stli_timerlist = TIMER_INITIALIZER(stli_poll, 0, 0);
+static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
 
 static int     stli_timeron;
 
index 523fd3c8bbaa75dd345224799990ec0c4f4e5e93..449d029ad4f40abc936fb85f6ee66f60511201a6 100644 (file)
@@ -14,7 +14,7 @@
  * `Sticky' modifier keys, 951006.
  *
  * 11-11-96: SAK should now work in the raw mode (Martin Mares)
- * 
+ *
  * Modified to provide 'generic' keyboard support by Hamish Macdonald
  * Merge with the m68k keyboard driver and split-off of the PC low-level
  * parts by Geert Uytterhoeven, May 1997
@@ -52,7 +52,7 @@ extern void ctrl_alt_del(void);
 /*
  * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on.
  * This seems a good reason to start with NumLock off. On HIL keyboards
- * of PARISC machines however there is no NumLock key and everyone expects the keypad 
+ * of PARISC machines however there is no NumLock key and everyone expects the keypad
  * to be used for numbers.
  */
 
@@ -76,17 +76,17 @@ void compute_shiftstate(void);
        k_meta,         k_ascii,        k_lock,         k_lowercase,\
        k_slock,        k_dead2,        k_ignore,       k_ignore
 
-typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value, 
+typedef void (k_handler_fn)(struct vc_data *vc, unsigned char value,
                            char up_flag, struct pt_regs *regs);
 static k_handler_fn K_HANDLERS;
 static k_handler_fn *k_handler[16] = { K_HANDLERS };
 
 #define FN_HANDLERS\
-       fn_null,        fn_enter,       fn_show_ptregs, fn_show_mem,\
-       fn_show_state,  fn_send_intr,   fn_lastcons,    fn_caps_toggle,\
-       fn_num,         fn_hold,        fn_scroll_forw, fn_scroll_back,\
-       fn_boot_it,     fn_caps_on,     fn_compose,     fn_SAK,\
-       fn_dec_console, fn_inc_console, fn_spawn_con,   fn_bare_num
+       fn_null,        fn_enter,       fn_show_ptregs, fn_show_mem,\
+       fn_show_state,  fn_send_intr,   fn_lastcons,    fn_caps_toggle,\
+       fn_num,         fn_hold,        fn_scroll_forw, fn_scroll_back,\
+       fn_boot_it,     fn_caps_on,     fn_compose,     fn_SAK,\
+       fn_dec_console, fn_inc_console, fn_spawn_con,   fn_bare_num
 
 typedef void (fn_handler_fn)(struct vc_data *vc, struct pt_regs *regs);
 static fn_handler_fn FN_HANDLERS;
@@ -159,13 +159,13 @@ static int sysrq_alt;
  */
 int getkeycode(unsigned int scancode)
 {
-       struct list_head * node;
+       struct list_head *node;
        struct input_dev *dev = NULL;
 
-       list_for_each(node,&kbd_handler.h_list) {
-               struct input_handle * handle = to_handle_h(node);
-               if (handle->dev->keycodesize) { 
-                       dev = handle->dev; 
+       list_for_each(node, &kbd_handler.h_list) {
+               struct input_handle *handle = to_handle_h(node);
+               if (handle->dev->keycodesize) {
+                       dev = handle->dev;
                        break;
                }
        }
@@ -181,15 +181,15 @@ int getkeycode(unsigned int scancode)
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-       struct list_head * node;
+       struct list_head *node;
        struct input_dev *dev = NULL;
        unsigned int i, oldkey;
 
-       list_for_each(node,&kbd_handler.h_list) {
+       list_for_each(node, &kbd_handler.h_list) {
                struct input_handle *handle = to_handle_h(node);
-               if (handle->dev->keycodesize) { 
-                       dev = handle->dev; 
-                       break; 
+               if (handle->dev->keycodesize) {
+                       dev = handle->dev;
+                       break;
                }
        }
 
@@ -200,7 +200,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
                return -EINVAL;
        if (keycode < 0 || keycode > KEY_MAX)
                return -EINVAL;
-       if (keycode >> (dev->keycodesize * 8))
+       if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
                return -EINVAL;
 
        oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
@@ -216,11 +216,11 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
 }
 
 /*
- * Making beeps and bells. 
+ * Making beeps and bells.
  */
 static void kd_nosound(unsigned long ignored)
 {
-       struct list_head * node;
+       struct list_head *node;
 
        list_for_each(node,&kbd_handler.h_list) {
                struct input_handle *handle = to_handle_h(node);
@@ -233,17 +233,16 @@ static void kd_nosound(unsigned long ignored)
        }
 }
 
-static struct timer_list kd_mksound_timer =
-               TIMER_INITIALIZER(kd_nosound, 0, 0);
+static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
 
 void kd_mksound(unsigned int hz, unsigned int ticks)
 {
-       struct list_head * node;
+       struct list_head *node;
 
        del_timer(&kd_mksound_timer);
 
        if (hz) {
-               list_for_each_prev(node,&kbd_handler.h_list) {
+               list_for_each_prev(node, &kbd_handler.h_list) {
                        struct input_handle *handle = to_handle_h(node);
                        if (test_bit(EV_SND, handle->dev->evbit)) {
                                if (test_bit(SND_TONE, handle->dev->sndbit)) {
@@ -338,19 +337,19 @@ static void to_utf8(struct vc_data *vc, ushort c)
        if (c < 0x80)
                /*  0******* */
                put_queue(vc, c);
-       else if (c < 0x800) {
+       else if (c < 0x800) {
                /* 110***** 10****** */
-               put_queue(vc, 0xc0 | (c >> 6)); 
+               put_queue(vc, 0xc0 | (c >> 6));
                put_queue(vc, 0x80 | (c & 0x3f));
-       } else {
+       } else {
                /* 1110**** 10****** 10****** */
                put_queue(vc, 0xe0 | (c >> 12));
                put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
                put_queue(vc, 0x80 | (c & 0x3f));
-       }
+       }
 }
 
-/* 
+/*
  * Called after returning from RAW mode or when changing consoles - recompute
  * shift_down[] and shift_state from key_down[] maybe called when keymap is
  * undefined, so that shiftkey release is seen
@@ -361,7 +360,7 @@ void compute_shiftstate(void)
 
        shift_state = 0;
        memset(shift_down, 0, sizeof(shift_down));
-       
+
        for (i = 0; i < ARRAY_SIZE(key_down); i++) {
 
                if (!key_down[i])
@@ -500,9 +499,9 @@ static void fn_dec_console(struct vc_data *vc, struct pt_regs *regs)
        if (want_console != -1)
                cur = want_console;
 
-       for (i = cur-1; i != cur; i--) {
+       for (i = cur - 1; i != cur; i--) {
                if (i == -1)
-                       i = MAX_NR_CONSOLES-1;
+                       i = MAX_NR_CONSOLES - 1;
                if (vc_cons_allocated(i))
                        break;
        }
@@ -568,9 +567,9 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs)
 
 static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
 {
-        if (spawnpid)
-          if(kill_proc(spawnpid, spawnsig, 1))
-            spawnpid = 0;
+       if (spawnpid)
+               if (kill_proc(spawnpid, spawnsig, 1))
+                       spawnpid = 0;
 }
 
 static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
@@ -604,8 +603,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag, struct
                return;
        if (value >= ARRAY_SIZE(fn_handler))
                return;
-       if ((kbd->kbdmode == VC_RAW || 
-            kbd->kbdmode == VC_MEDIUMRAW) && 
+       if ((kbd->kbdmode == VC_RAW ||
+            kbd->kbdmode == VC_MEDIUMRAW) &&
             value != KVAL(K_SAK))
                return;         /* SAK is allowed even in raw mode */
        fn_handler[value](vc, regs);
@@ -895,11 +894,11 @@ static inline unsigned char getleds(void)
 
 static void kbd_bh(unsigned long dummy)
 {
-       struct list_head * node;
+       struct list_head *node;
        unsigned char leds = getleds();
 
        if (leds != ledstate) {
-               list_for_each(node,&kbd_handler.h_list) {
+               list_for_each(node, &kbd_handler.h_list) {
                        struct input_handle * handle = to_handle_h(node);
                        input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
                        input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
@@ -964,11 +963,11 @@ static int sparc_l1_a_state = 0;
 extern void sun_do_break(void);
 #endif
 
-static int emulate_raw(struct vc_data *vc, unsigned int keycode, 
+static int emulate_raw(struct vc_data *vc, unsigned int keycode,
                       unsigned char up_flag)
 {
        if (keycode > 255 || !x86_keycodes[keycode])
-               return -1; 
+               return -1;
 
        switch (keycode) {
                case KEY_PAUSE:
@@ -982,7 +981,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
                case KEY_HANJA:
                        if (!up_flag) put_queue(vc, 0xf2);
                        return 0;
-       } 
+       }
 
        if (keycode == KEY_SYSRQ && sysrq_alt) {
                put_queue(vc, 0x54 | up_flag);
@@ -1105,11 +1104,12 @@ static void kbd_keycode(unsigned int keycode, int down,
        else
                clear_bit(keycode, key_down);
 
-       if (rep && (!vc_kbd_mode(kbd, VC_REPEAT) || (tty && 
-               (!L_ECHO(tty) && tty->driver->chars_in_buffer(tty))))) {
+       if (rep &&
+           (!vc_kbd_mode(kbd, VC_REPEAT) ||
+            (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
                /*
                 * Don't repeat a key if the input buffers are not empty and the
-                * characters get aren't echoed locally. This makes key repeat 
+                * characters get aren't echoed locally. This makes key repeat
                 * usable with slow applications and under heavy loads.
                 */
                return;
@@ -1131,7 +1131,8 @@ static void kbd_keycode(unsigned int keycode, int down,
        type = KTYP(keysym);
 
        if (type < 0xf0) {
-               if (down && !raw_mode) to_utf8(vc, keysym);
+               if (down && !raw_mode)
+                       to_utf8(vc, keysym);
                return;
        }
 
@@ -1155,7 +1156,7 @@ static void kbd_keycode(unsigned int keycode, int down,
                kbd->slockstate = 0;
 }
 
-static void kbd_event(struct input_handle *handle, unsigned int event_type, 
+static void kbd_event(struct input_handle *handle, unsigned int event_type,
                      unsigned int event_code, int value)
 {
        if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
@@ -1167,15 +1168,13 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
        schedule_console_callback();
 }
 
-static char kbd_name[] = "kbd";
-
 /*
  * When a keyboard (or other input device) is found, the kbd_connect
  * function is called. The function then looks at the device, and if it
  * likes it, it can open it and get events from it. In this (kbd_connect)
  * function, we should decide which VT to bind that keyboard to initially.
  */
-static struct input_handle *kbd_connect(struct input_handler *handler, 
+static struct input_handle *kbd_connect(struct input_handler *handler,
                                        struct input_dev *dev,
                                        struct input_device_id *id)
 {
@@ -1183,18 +1182,19 @@ static struct input_handle *kbd_connect(struct input_handler *handler,
        int i;
 
        for (i = KEY_RESERVED; i < BTN_MISC; i++)
-               if (test_bit(i, dev->keybit)) break;
+               if (test_bit(i, dev->keybit))
+                       break;
 
-       if ((i == BTN_MISC) && !test_bit(EV_SND, dev->evbit)) 
+       if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
                return NULL;
 
-       if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) 
+       if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
                return NULL;
        memset(handle, 0, sizeof(struct input_handle));
 
        handle->dev = dev;
        handle->handler = handler;
-       handle->name = kbd_name;
+       handle->name = "kbd";
 
        input_open_device(handle);
        kbd_refresh_leds(handle);
@@ -1213,11 +1213,11 @@ static struct input_device_id kbd_ids[] = {
                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
                 .evbit = { BIT(EV_KEY) },
         },
-       
+
        {
                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
                 .evbit = { BIT(EV_SND) },
-        },     
+        },
 
        { },    /* Terminating entry */
 };
index cf01a720eb2eff74a8154510cfd970ebbfb60f8d..b771611461445548bed26bd09df0c06fe2265587 100644 (file)
@@ -613,10 +613,15 @@ static struct miscdevice lcd_dev = {
 
 static int lcd_init(void)
 {
+       int ret;
        unsigned long data;
 
        pr_info("%s\n", LCD_DRIVER);
-       misc_register(&lcd_dev);
+       ret = misc_register(&lcd_dev);
+       if (ret) {
+               printk(KERN_WARNING LCD "Unable to register misc device.\n");
+               return ret;
+       }
 
        /* Check region? Naaah! Just snarf it up. */
 /*     request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/
index 59eebe5a035f1c7691656f389c75af261769c0eb..2afb9038dbc5752abbdf55dc1dc3c8a9737bd841 100644 (file)
 #include <linux/console.h>
 #include <linux/device.h>
 #include <linux/wait.h>
+#include <linux/jiffies.h>
 
 #include <linux/parport.h>
 #undef LP_STATS
@@ -307,7 +308,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
                        (LP_F(minor) & LP_ABORT));
 
 #ifdef LP_STATS
-       if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
+       if (time_after(jiffies, lp_table[minor].lastcall + LP_TIME(minor)))
                lp_table[minor].runchars = 0;
 
        lp_table[minor].lastcall = jiffies;
index d0ef1ae412981d774289575dba2ea8a866975e37..45d012d85e8c3d436d33c46e1b809f8dee9216d3 100644 (file)
@@ -1058,8 +1058,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
                 */
                timeout = jiffies + HZ;
                while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(5);
+                       schedule_timeout_interruptible(5);
                        if (time_after(jiffies, timeout))
                                break;
                }
@@ -1080,10 +1079,8 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
        info->event = 0;
        info->tty = NULL;
        if (info->blocked_open) {
-               if (info->close_delay) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(info->close_delay);
-               }
+               if (info->close_delay)
+                       schedule_timeout_interruptible(info->close_delay);
                wake_up_interruptible(&info->open_wait);
        }
 
@@ -1801,8 +1798,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
                printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
 #endif
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(char_time);
+               schedule_timeout_interruptible(char_time);
                if (signal_pending(current))
                        break;
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
index 09103b3d8f05a26beae37b61d6160ccfb7911fc2..c9bdf544ed2cd1126f6d67840c082ee6bb53d42e 100644 (file)
@@ -62,7 +62,7 @@
 
 static inline unsigned char *alloc_buf(void)
 {
-       int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+       unsigned int prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 
        if (PAGE_SIZE != N_TTY_BUF_SIZE)
                return kmalloc(N_TTY_BUF_SIZE, prio);
index 7a0c7464812492166a14ebbd778c6e60cfb6dc0a..02d7f046c10aeae25e831b2f15f9f85e63a22d99 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/pcmcia/synclink_cs.c
  *
- * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.34 2005/09/08 13:20:54 paulkf Exp $
  *
  * Device driver for Microgate SyncLink PC Card
  * multiprotocol serial adapter.
@@ -472,7 +472,7 @@ module_param_array(dosyncppp, int, NULL, 0);
 MODULE_LICENSE("GPL");
 
 static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.26 $";
+static char *driver_version = "$Revision: 4.34 $";
 
 static struct tty_driver *serial_driver;
 
@@ -1457,6 +1457,8 @@ static int startup(MGSLPC_INFO * info)
 
        info->pending_bh = 0;
        
+       memset(&info->icount, 0, sizeof(info->icount));
+
        init_timer(&info->tx_timer);
        info->tx_timer.data = (unsigned long)info;
        info->tx_timer.function = tx_timeout;
@@ -1946,9 +1948,13 @@ static int get_stats(MGSLPC_INFO * info, struct mgsl_icount __user *user_icount)
        int err;
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("get_params(%s)\n", info->device_name);
-       COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
-       if (err)
-               return -EFAULT;
+       if (!user_icount) {
+               memset(&info->icount, 0, sizeof(info->icount));
+       } else {
+               COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+               if (err)
+                       return -EFAULT;
+       }
        return 0;
 }
 
index da32889d22c0992a32f00560f2fbeec41519878f..49f3997fd251d95cfaec443d98f5a15037f52c68 100644 (file)
@@ -149,15 +149,14 @@ static int pty_write_room(struct tty_struct *tty)
 static int pty_chars_in_buffer(struct tty_struct *tty)
 {
        struct tty_struct *to = tty->link;
-       ssize_t (*chars_in_buffer)(struct tty_struct *);
        int count;
 
        /* We should get the line discipline lock for "tty->link" */
-       if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer))
+       if (!to || !to->ldisc.chars_in_buffer)
                return 0;
 
        /* The ldisc must report 0 if no characters available to be read */
-       count = chars_in_buffer(to);
+       count = to->ldisc.chars_in_buffer(to);
 
        if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
 
index 37c8bea8e2b003a048e18b452ef1cc26f8b16fb6..ea2d54be4843e07c17efc83ebf14a6677e599a5d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
+ * $Id: synclink.c,v 4.37 2005/09/07 13:13:19 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -141,9 +141,9 @@ static MGSL_PARAMS default_params = {
 typedef struct _DMABUFFERENTRY
 {
        u32 phys_addr;  /* 32-bit flat physical address of data buffer */
-       u16 count;      /* buffer size/data count */
-       u16 status;     /* Control/status field */
-       u16 rcc;        /* character count field */
+       volatile u16 count;     /* buffer size/data count */
+       volatile u16 status;    /* Control/status field */
+       volatile u16 rcc;       /* character count field */
        u16 reserved;   /* padding required by 16C32 */
        u32 link;       /* 32-bit flat link to next buffer entry */
        char *virt_addr;        /* virtual address of data buffer */
@@ -896,7 +896,7 @@ module_param_array(txdmabufs, int, NULL, 0);
 module_param_array(txholdbufs, int, NULL, 0);
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.28 $";
+static char *driver_version = "$Revision: 4.37 $";
 
 static int synclink_init_one (struct pci_dev *dev,
                                     const struct pci_device_id *ent);
@@ -1814,6 +1814,8 @@ static int startup(struct mgsl_struct * info)
 
        info->pending_bh = 0;
        
+       memset(&info->icount, 0, sizeof(info->icount));
+
        init_timer(&info->tx_timer);
        info->tx_timer.data = (unsigned long)info;
        info->tx_timer.function = mgsl_tx_timeout;
@@ -2470,12 +2472,12 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *
                printk("%s(%d):mgsl_get_params(%s)\n",
                         __FILE__,__LINE__, info->device_name);
                        
-       COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
-       if (err) {
-               if ( debug_level >= DEBUG_LEVEL_INFO )
-                       printk( "%s(%d):mgsl_get_stats(%s) user buffer copy failed\n",
-                               __FILE__,__LINE__,info->device_name);
-               return -EFAULT;
+       if (!user_icount) {
+               memset(&info->icount, 0, sizeof(info->icount));
+       } else {
+               COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+               if (err)
+                       return -EFAULT;
        }
        
        return 0;
@@ -6149,6 +6151,11 @@ static void usc_set_async_mode( struct mgsl_struct *info )
                usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
        }
 
+       if (info->params.loopback) {
+               info->loopback_bits = 0x300;
+               outw(0x0300, info->io_base + CCAR);
+       }
+
 }      /* end of usc_set_async_mode() */
 
 /* usc_loopback_frame()
index 8982eafd0fb7126411ef58b8d21df20c841bb747..6fb165cf8a61ca0ca4be7532e00909f342bb4f03 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.34 2005/03/04 15:07:10 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -486,7 +486,7 @@ module_param_array(maxframe, int, NULL, 0);
 module_param_array(dosyncppp, int, NULL, 0);
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.34 $";
+static char *driver_version = "$Revision: 4.38 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -555,7 +555,6 @@ static int  set_txidle(SLMP_INFO *info, int idle_mode);
 static int  tx_enable(SLMP_INFO *info, int enable);
 static int  tx_abort(SLMP_INFO *info);
 static int  rx_enable(SLMP_INFO *info, int enable);
-static int  map_status(int signals);
 static int  modem_input_wait(SLMP_INFO *info,int arg);
 static int  wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
 static int  tiocmget(struct tty_struct *tty, struct file *file);
@@ -644,7 +643,7 @@ static unsigned char tx_active_fifo_level = 16;     // tx request FIFO activation le
 static unsigned char tx_negate_fifo_level = 32;        // tx request FIFO negation level in bytes
 
 static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x00800029;
+static u32 lcr1_brdr_value = 0x00800028;
 
 static u32 read_ahead_count = 8;
 
@@ -2749,6 +2748,8 @@ static int startup(SLMP_INFO * info)
 
        info->pending_bh = 0;
 
+       memset(&info->icount, 0, sizeof(info->icount));
+
        /* program hardware for current parameters */
        reset_port(info);
 
@@ -2952,12 +2953,12 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
                printk("%s(%d):%s get_params()\n",
                         __FILE__,__LINE__, info->device_name);
 
-       COPY_TO_USER(err,user_icount, &info->icount, sizeof(struct mgsl_icount));
-       if (err) {
-               if ( debug_level >= DEBUG_LEVEL_INFO )
-                       printk( "%s(%d):%s get_stats() user buffer copy failed\n",
-                               __FILE__,__LINE__,info->device_name);
-               return -EFAULT;
+       if (!user_icount) {
+               memset(&info->icount, 0, sizeof(info->icount));
+       } else {
+               COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+               if (err)
+                       return -EFAULT;
        }
 
        return 0;
@@ -3108,16 +3109,6 @@ static int rx_enable(SLMP_INFO * info, int enable)
        return 0;
 }
 
-static int map_status(int signals)
-{
-       /* Map status bits to API event bits */
-
-       return ((signals & SerialSignal_DSR) ? MgslEvent_DsrActive : MgslEvent_DsrInactive) +
-              ((signals & SerialSignal_CTS) ? MgslEvent_CtsActive : MgslEvent_CtsInactive) +
-              ((signals & SerialSignal_DCD) ? MgslEvent_DcdActive : MgslEvent_DcdInactive) +
-              ((signals & SerialSignal_RI)  ? MgslEvent_RiActive : MgslEvent_RiInactive);
-}
-
 /* wait for specified event to occur
  */
 static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
@@ -3144,7 +3135,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
 
        /* return immediately if state matches requested events */
        get_signals(info);
-       s = map_status(info->serial_signals);
+       s = info->serial_signals;
 
        events = mask &
                ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
@@ -4488,11 +4479,13 @@ void async_mode(SLMP_INFO *info)
        /* MD2, Mode Register 2
         *
         * 07..02  Reserved, must be 0
-        * 01..00  CNCT<1..0> Channel connection, 0=normal
+        * 01..00  CNCT<1..0> Channel connection, 00=normal 11=local loopback
         *
         * 0000 0000
         */
        RegValue = 0x00;
+       if (info->params.loopback)
+               RegValue |= (BIT1 + BIT0);
        write_reg(info, MD2, RegValue);
 
        /* RXS, Receive clock source
@@ -4573,9 +4566,6 @@ void async_mode(SLMP_INFO *info)
        write_reg(info, IE2, info->ie2_value);
 
        set_rate( info, info->params.data_rate * 16 );
-
-       if (info->params.loopback)
-               enable_loopback(info,1);
 }
 
 /* Program the SCA for HDLC communications.
index 9d657127f313f21e653b0dd7b49fc539a66a0501..e5953f3433f3ea425ecd966c752a35ec68b63901 100644 (file)
@@ -469,21 +469,19 @@ static void tty_ldisc_enable(struct tty_struct *tty)
  
 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
-       int     retval = 0;
-       struct  tty_ldisc o_ldisc;
+       int retval = 0;
+       struct tty_ldisc o_ldisc;
        char buf[64];
        int work;
        unsigned long flags;
        struct tty_ldisc *ld;
+       struct tty_struct *o_tty;
 
        if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
                return -EINVAL;
 
 restart:
 
-       if (tty->ldisc.num == ldisc)
-               return 0;       /* We are already in the desired discipline */
-       
        ld = tty_ldisc_get(ldisc);
        /* Eduardo Blanco <ejbs@cs.cs.com.uy> */
        /* Cyrus Durgin <cider@speakeasy.org> */
@@ -494,45 +492,74 @@ restart:
        if (ld == NULL)
                return -EINVAL;
 
-       o_ldisc = tty->ldisc;
-
        tty_wait_until_sent(tty, 0);
 
+       if (tty->ldisc.num == ldisc) {
+               tty_ldisc_put(ldisc);
+               return 0;
+       }
+
+       o_ldisc = tty->ldisc;
+       o_tty = tty->link;
+
        /*
         *      Make sure we don't change while someone holds a
         *      reference to the line discipline. The TTY_LDISC bit
         *      prevents anyone taking a reference once it is clear.
         *      We need the lock to avoid racing reference takers.
         */
-        
+
        spin_lock_irqsave(&tty_ldisc_lock, flags);
-       if(tty->ldisc.refcount)
-       {
-               /* Free the new ldisc we grabbed. Must drop the lock
-                  first. */
+       if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
+               if(tty->ldisc.refcount) {
+                       /* Free the new ldisc we grabbed. Must drop the lock
+                          first. */
+                       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+                       tty_ldisc_put(ldisc);
+                       /*
+                        * There are several reasons we may be busy, including
+                        * random momentary I/O traffic. We must therefore
+                        * retry. We could distinguish between blocking ops
+                        * and retries if we made tty_ldisc_wait() smarter. That
+                        * is up for discussion.
+                        */
+                       if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+                               return -ERESTARTSYS;
+                       goto restart;
+               }
+               if(o_tty && o_tty->ldisc.refcount) {
+                       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+                       tty_ldisc_put(ldisc);
+                       if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0)
+                               return -ERESTARTSYS;
+                       goto restart;
+               }
+       }
+
+       /* if the TTY_LDISC bit is set, then we are racing against another ldisc change */
+
+       if (!test_bit(TTY_LDISC, &tty->flags)) {
                spin_unlock_irqrestore(&tty_ldisc_lock, flags);
                tty_ldisc_put(ldisc);
-               /*
-                * There are several reasons we may be busy, including
-                * random momentary I/O traffic. We must therefore
-                * retry. We could distinguish between blocking ops
-                * and retries if we made tty_ldisc_wait() smarter. That
-                * is up for discussion.
-                */
-               if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
-                       return -ERESTARTSYS;                    
+               ld = tty_ldisc_ref_wait(tty);
+               tty_ldisc_deref(ld);
                goto restart;
        }
-       clear_bit(TTY_LDISC, &tty->flags);      
+
+       clear_bit(TTY_LDISC, &tty->flags);
        clear_bit(TTY_DONT_FLIP, &tty->flags);
+       if (o_tty) {
+               clear_bit(TTY_LDISC, &o_tty->flags);
+               clear_bit(TTY_DONT_FLIP, &o_tty->flags);
+       }
        spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-       
+
        /*
         *      From this point on we know nobody has an ldisc
         *      usage reference, nor can they obtain one until
         *      we say so later on.
         */
-        
+
        work = cancel_delayed_work(&tty->flip.work);
        /*
         * Wait for ->hangup_work and ->flip.work handlers to terminate
@@ -583,10 +610,12 @@ restart:
         */
         
        tty_ldisc_enable(tty);
+       if (o_tty)
+               tty_ldisc_enable(o_tty);
        
        /* Restart it in case no characters kick it off. Safe if
           already running */
-       if(work)
+       if (work)
                schedule_delayed_work(&tty->flip.work, 1);
        return retval;
 }
@@ -2425,6 +2454,7 @@ static void __do_SAK(void *arg)
        int             i;
        struct file     *filp;
        struct tty_ldisc *disc;
+       struct fdtable *fdt;
        
        if (!tty)
                return;
@@ -2450,8 +2480,9 @@ static void __do_SAK(void *arg)
                }
                task_lock(p);
                if (p->files) {
-                       spin_lock(&p->files->file_lock);
-                       for (i=0; i < p->files->max_fds; i++) {
+                       rcu_read_lock();
+                       fdt = files_fdtable(p->files);
+                       for (i=0; i < fdt->max_fds; i++) {
                                filp = fcheck_files(p->files, i);
                                if (!filp)
                                        continue;
@@ -2464,7 +2495,7 @@ static void __do_SAK(void *arg)
                                        break;
                                }
                        }
-                       spin_unlock(&p->files->file_lock);
+                       rcu_read_unlock();
                }
                task_unlock(p);
        } while_each_task_pid(session, PIDTYPE_SID, p);
index b8d0c290b0dbf137152a03d3a992ad07e308738a..1e33cb032e073ba40a0c9e5b14ed705f777c9c82 100644 (file)
@@ -751,6 +751,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
        unsigned int old_cols, old_rows, old_row_size, old_screen_size;
        unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+       unsigned int end;
        unsigned short *newscreen;
 
        WARN_CONSOLE_UNLOCKED();
@@ -794,20 +795,44 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
        old_origin = vc->vc_origin;
        new_origin = (long) newscreen;
        new_scr_end = new_origin + new_screen_size;
-       if (new_rows < old_rows)
-               old_origin += (old_rows - new_rows) * old_row_size;
+
+       if (vc->vc_y > new_rows) {
+               if (old_rows - vc->vc_y < new_rows) {
+                       /*
+                        * Cursor near the bottom, copy contents from the
+                        * bottom of buffer
+                        */
+                       old_origin += (old_rows - new_rows) * old_row_size;
+                       end = vc->vc_scr_end;
+               } else {
+                       /*
+                        * Cursor is in no man's land, copy 1/2 screenful
+                        * from the top and bottom of cursor position
+                        */
+                       old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+                       end = old_origin + new_screen_size;
+               }
+       } else
+               /*
+                * Cursor near the top, copy contents from the top of buffer
+                */
+               end = (old_rows > new_rows) ? old_origin + new_screen_size :
+                       vc->vc_scr_end;
 
        update_attr(vc);
 
-       while (old_origin < vc->vc_scr_end) {
-               scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
+       while (old_origin < end) {
+               scr_memcpyw((unsigned short *) new_origin,
+                           (unsigned short *) old_origin, rlth);
                if (rrem)
-                       scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
+                       scr_memsetw((void *)(new_origin + rlth),
+                                   vc->vc_video_erase_char, rrem);
                old_origin += old_row_size;
                new_origin += new_row_size;
        }
        if (new_scr_end > new_origin)
-               scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+               scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+                           new_scr_end - new_origin);
        if (vc->vc_kmalloced)
                kfree(vc->vc_screenbuf);
        vc->vc_screenbuf = newscreen;
index c9b301dccec36427caa4262332b261401f11a0bc..7fc2188386d96b56ac062cf4830736a6f6222a79 100644 (file)
@@ -59,7 +59,7 @@ static unsigned long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
 static int mixcomwd_timer_alive;
-static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(mixcomwd_timer, NULL, 0, 0);
 static char expect_close;
 
 static int nowayout = WATCHDOG_NOWAYOUT;
index f174aee659e5e0d086314e6ba3ebcfb3c92249cc..9e9cf1407311f92eabc53cf702913f70537b6c17 100644 (file)
@@ -560,7 +560,7 @@ ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
 EXPORT_SYMBOL_GPL(__ide_abort);
 
 /**
- *     ide_abort       -       abort pending IDE operatins
+ *     ide_abort       -       abort pending IDE operations
  *     @drive: drive the error occurred on
  *     @msg: message to report
  *
@@ -623,7 +623,7 @@ static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
  *     @drive: drive the completion interrupt occurred on
  *
  *     drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
- *     We do any necessary daya reading and then wait for the drive to
+ *     We do any necessary data reading and then wait for the drive to
  *     go non busy. At that point we may read the error data and complete
  *     the request
  */
@@ -773,7 +773,7 @@ EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
 
 /**
  *     execute_drive_command   -       issue special drive command
- *     @drive: the drive to issue th command on
+ *     @drive: the drive to issue the command on
  *     @rq: the request structure holding the command
  *
  *     execute_drive_cmd() issues a special drive command,  usually 
index 5a3dc46008e64895fd5ccbe5e48dd3d32bd7a079..ee38e6b143a4c2f453386d21f19f646217bf1f74 100644 (file)
@@ -2903,8 +2903,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
                } else if (!(tape->sense_key == 2 && tape->asc == 4 &&
                             (tape->ascq == 1 || tape->ascq == 8)))
                        return -EIO;
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(HZ / 10);
+               msleep(100);
        }
        return -EIO;
 }
index c1196ce15b4d465ba3eaa91be1d3210d99d69b6d..2fcfac6e967aa221fec1053568c4d6e48715e2e9 100644 (file)
@@ -27,6 +27,7 @@
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
+#include <linux/kernel.h>
 #include <linux/hdreg.h>
 
 #define XFER_PIO_5             0x0d
@@ -96,11 +97,9 @@ static struct ide_timing ide_timing[] = {
 #define IDE_TIMING_UDMA                0x80
 #define IDE_TIMING_ALL         0xff
 
-#define MIN(a,b)       ((a)<(b)?(a):(b))
-#define MAX(a,b)       ((a)>(b)?(a):(b))
-#define FIT(v,min,max) MAX(MIN(v,max),min)
-#define ENOUGH(v,unit) (((v)-1)/(unit)+1)
-#define EZ(v,unit)     ((v)?ENOUGH(v,unit):0)
+#define FIT(v,vmin,vmax)       max_t(short,min_t(short,v,vmax),vmin)
+#define ENOUGH(v,unit)         (((v)-1)/(unit)+1)
+#define EZ(v,unit)             ((v)?ENOUGH(v,unit):0)
 
 #define XFER_MODE      0xf0
 #define XFER_UDMA_133  0x48
@@ -188,14 +187,14 @@ static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int
 
 static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
 {
-       if (what & IDE_TIMING_SETUP  ) m->setup   = MAX(a->setup,   b->setup);
-       if (what & IDE_TIMING_ACT8B  ) m->act8b   = MAX(a->act8b,   b->act8b);
-       if (what & IDE_TIMING_REC8B  ) m->rec8b   = MAX(a->rec8b,   b->rec8b);
-       if (what & IDE_TIMING_CYC8B  ) m->cyc8b   = MAX(a->cyc8b,   b->cyc8b);
-       if (what & IDE_TIMING_ACTIVE ) m->active  = MAX(a->active,  b->active);
-       if (what & IDE_TIMING_RECOVER) m->recover = MAX(a->recover, b->recover);
-       if (what & IDE_TIMING_CYCLE  ) m->cycle   = MAX(a->cycle,   b->cycle);
-       if (what & IDE_TIMING_UDMA   ) m->udma    = MAX(a->udma,    b->udma);
+       if (what & IDE_TIMING_SETUP  ) m->setup   = max(a->setup,   b->setup);
+       if (what & IDE_TIMING_ACT8B  ) m->act8b   = max(a->act8b,   b->act8b);
+       if (what & IDE_TIMING_REC8B  ) m->rec8b   = max(a->rec8b,   b->rec8b);
+       if (what & IDE_TIMING_CYC8B  ) m->cyc8b   = max(a->cyc8b,   b->cyc8b);
+       if (what & IDE_TIMING_ACTIVE ) m->active  = max(a->active,  b->active);
+       if (what & IDE_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+       if (what & IDE_TIMING_CYCLE  ) m->cycle   = max(a->cycle,   b->cycle);
+       if (what & IDE_TIMING_UDMA   ) m->udma    = max(a->udma,    b->udma);
 }
 
 static struct ide_timing* ide_timing_find_mode(short speed)
index f1d1ec4e967718946e332c3fb0b43be2b1182def..0ccf85fcee3478669dfb5f2a1827d9c5494a7082 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/ide.h>
 #include <linux/hdreg.h>
 #include <linux/major.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -340,8 +341,7 @@ static void ide_config(dev_link_t *link)
                break;
            }
        }
-       __set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ/10);
+       msleep(100);
     }
 
     if (hd < 0) {
@@ -454,9 +454,12 @@ int ide_event(event_t event, int priority,
 static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_FUNC_ID(4),
        PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+       PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),        /* Toshiba */
        PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
+       PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),        /* Samsung */
        PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
-       PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
+       PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200),        /* Lexar */
        PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
        PCMCIA_DEVICE_PROD_ID123("CDROM", "IDE", "MCD-601p", 0x1b9179ca, 0xede88951, 0x0d902f74),
        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
@@ -481,6 +484,7 @@ static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
        PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
        PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
+       PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
        PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
        PCMCIA_DEVICE_NULL,
 };
index 7b64db10d1b03cd82786cbb8ca34852c7df6e518..127619a109eda2ef119c9deeecd44793ae53a834 100644 (file)
@@ -1334,9 +1334,13 @@ static int __devinit init_hpt366(struct pci_dev *dev)
 static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
 {
        int ret = 0;
-       /* FIXME: Not portable */
+
+       /*
+        * FIXME: Not portable. Also, why do we enable the ROM in the first place?
+        * We don't seem to be using it.
+        */
        if (dev->resource[PCI_ROM_RESOURCE].start)
-               pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+               pci_write_config_dword(dev, PCI_ROM_ADDRESS,
                        dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
 
        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
index 06759b36afea0cc87896d844e3718a35ff4f68ca..9d6facf2f78f5751f3da65890ea94cf3f5419143 100644 (file)
@@ -883,7 +883,7 @@ static int __video1394_ioctl(struct file *file,
                              v.channel);
                }
 
-               if (copy_to_user((void *)arg, &v, sizeof(v))) {
+               if (copy_to_user(argp, &v, sizeof(v))) {
                        /* FIXME : free allocated dma resources */
                        return -EFAULT;
                }
index 32cdfb30e9b46e1cead064e74f7a06ded25495e1..325d502e25cdb30df585ecb68a642ac9aeb5818b 100644 (file)
@@ -8,15 +8,26 @@ config INFINIBAND
          any protocols you wish to use as well as drivers for your
          InfiniBand hardware.
 
-config INFINIBAND_USER_VERBS
-       tristate "InfiniBand userspace verbs support"
+config INFINIBAND_USER_MAD
+       tristate "InfiniBand userspace MAD support"
        depends on INFINIBAND
        ---help---
-         Userspace InfiniBand verbs support.  This is the kernel side
-         of userspace verbs, which allows userspace processes to
-         directly access InfiniBand hardware for fast-path
-         operations.  You will also need libibverbs and a hardware
-         driver library from <http://www.openib.org>.
+         Userspace InfiniBand Management Datagram (MAD) support.  This
+         is the kernel side of the userspace MAD support, which allows
+         userspace processes to send and receive MADs. You will also 
+         need libibumad from <http://www.openib.org>.
+
+config INFINIBAND_USER_ACCESS
+       tristate "InfiniBand userspace access (verbs and CM)"
+       depends on INFINIBAND
+       ---help---
+         Userspace InfiniBand access support.  This enables the
+         kernel side of userspace verbs and the userspace
+         communication manager (CM).  This allows userspace processes
+         to set up connections and directly access InfiniBand
+         hardware for fast-path operations.  You will also need
+         libibverbs, libibcm and a hardware driver library from
+         <http://www.openib.org>.
 
 source "drivers/infiniband/hw/mthca/Kconfig"
 
index 678a7e097f329de2e3e6b926443807babf2ccdf4..ec3353f24b27598ba4cd4400ce8b13ab29aacc6d 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_INFINIBAND) +=            ib_core.o ib_mad.o ib_sa.o \
-                                       ib_cm.o ib_umad.o ib_ucm.o
-obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
+                                       ib_cm.o
+obj-$(CONFIG_INFINIBAND_USER_MAD) +=   ib_umad.o
+obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=        ib_uverbs.o ib_ucm.o
 
 ib_core-y :=                   packer.o ud_header.o verbs.o sysfs.o \
                                device.o fmr_pool.o cache.o
index 4de93ba274a61202e7e9d29d494826a148c79ac2..54db6d4831f1abd922651436c4fd07a36ad53a92 100644 (file)
@@ -173,7 +173,8 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv,
        if (IS_ERR(ah))
                return PTR_ERR(ah);
 
-       m = ib_create_send_mad(mad_agent, 1, cm_id_priv->av.pkey_index,
+       m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, 
+                              cm_id_priv->av.pkey_index,
                               ah, 0, sizeof(struct ib_mad_hdr),
                               sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),
                               GFP_ATOMIC);
@@ -536,6 +537,7 @@ struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
        cm_id_priv->id.state = IB_CM_IDLE;
        cm_id_priv->id.cm_handler = cm_handler;
        cm_id_priv->id.context = context;
+       cm_id_priv->id.remote_cm_qpn = 1;
        ret = cm_alloc_id(cm_id_priv);
        if (ret)
                goto error;
@@ -1313,6 +1315,7 @@ error3:   atomic_dec(&cm_id_priv->refcount);
        cm_deref_id(listen_cm_id_priv);
        cm_cleanup_timewait(cm_id_priv->timewait_info);
 error2:        kfree(cm_id_priv->timewait_info);
+       cm_id_priv->timewait_info = NULL;
 error1:        ib_destroy_cm_id(&cm_id_priv->id);
        return ret;
 }
index 43fd805e02659ce6f81befac85696c34f47beb9f..2bd8b1cc57c4c925fe8db42ecfb6c8a82797dc14 100644 (file)
@@ -593,7 +593,8 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
                rmpp_mad->rmpp_hdr.paylen_newwin =
                        cpu_to_be32(mad_send_wr->total_seg *
                                    (sizeof(struct ib_rmpp_mad) -
-                                      offsetof(struct ib_rmpp_mad, data)));
+                                      offsetof(struct ib_rmpp_mad, data)) -
+                                   mad_send_wr->pad);
                mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
        } else {
                mad_send_wr->send_wr.num_sge = 2;
@@ -602,6 +603,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
                mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) -
                                                 mad_send_wr->data_offset;
                mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey;
+               rmpp_mad->rmpp_hdr.paylen_newwin = 0;
        }
 
        if (mad_send_wr->seg_num == mad_send_wr->total_seg) {
index 126ac80db7b84f3e71b83211188b8b8024e07912..78de2dd1a4f2560ccdcaa8bfd3801b6f6b6c544d 100644 (file)
@@ -113,32 +113,6 @@ static DEFINE_IDR(query_idr);
 static spinlock_t tid_lock;
 static u32 tid;
 
-enum {
-       IB_SA_ATTR_CLASS_PORTINFO    = 0x01,
-       IB_SA_ATTR_NOTICE            = 0x02,
-       IB_SA_ATTR_INFORM_INFO       = 0x03,
-       IB_SA_ATTR_NODE_REC          = 0x11,
-       IB_SA_ATTR_PORT_INFO_REC     = 0x12,
-       IB_SA_ATTR_SL2VL_REC         = 0x13,
-       IB_SA_ATTR_SWITCH_REC        = 0x14,
-       IB_SA_ATTR_LINEAR_FDB_REC    = 0x15,
-       IB_SA_ATTR_RANDOM_FDB_REC    = 0x16,
-       IB_SA_ATTR_MCAST_FDB_REC     = 0x17,
-       IB_SA_ATTR_SM_INFO_REC       = 0x18,
-       IB_SA_ATTR_LINK_REC          = 0x20,
-       IB_SA_ATTR_GUID_INFO_REC     = 0x30,
-       IB_SA_ATTR_SERVICE_REC       = 0x31,
-       IB_SA_ATTR_PARTITION_REC     = 0x33,
-       IB_SA_ATTR_RANGE_REC         = 0x34,
-       IB_SA_ATTR_PATH_REC          = 0x35,
-       IB_SA_ATTR_VL_ARB_REC        = 0x36,
-       IB_SA_ATTR_MC_GROUP_REC      = 0x37,
-       IB_SA_ATTR_MC_MEMBER_REC     = 0x38,
-       IB_SA_ATTR_TRACE_REC         = 0x39,
-       IB_SA_ATTR_MULTI_PATH_REC    = 0x3a,
-       IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b
-};
-
 #define PATH_REC_FIELD(field) \
        .struct_offset_bytes = offsetof(struct ib_sa_path_rec, field),          \
        .struct_size_bytes   = sizeof ((struct ib_sa_path_rec *) 0)->field,     \
@@ -431,8 +405,8 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
            event->event == IB_EVENT_LID_CHANGE  ||
            event->event == IB_EVENT_PKEY_CHANGE ||
            event->event == IB_EVENT_SM_CHANGE) {
-               struct ib_sa_device *sa_dev =
-                       ib_get_client_data(event->device, &sa_client);
+               struct ib_sa_device *sa_dev;
+               sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
 
                schedule_work(&sa_dev->port[event->element.port_num -
                                            sa_dev->start_port].update_task);
index 79595826ccc7392aa2e9d05c1ad45454eedfccc0..d0f0b0a2edd33820803654622a5852152502fa5a 100644 (file)
@@ -72,7 +72,6 @@ enum {
 
 static struct semaphore ctx_id_mutex;
 static struct idr       ctx_id_table;
-static int              ctx_id_rover = 0;
 
 static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
 {
@@ -97,33 +96,16 @@ static void ib_ucm_ctx_put(struct ib_ucm_context *ctx)
                wake_up(&ctx->wait);
 }
 
-static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id)
+static inline int ib_ucm_new_cm_id(int event)
 {
-       struct ib_ucm_context *ctx;
-       struct ib_ucm_event *uevent;
-
-       down(&ctx_id_mutex);
-       ctx = idr_find(&ctx_id_table, id);
-       if (!ctx)
-               ctx = ERR_PTR(-ENOENT);
-       else if (ctx->file != file)
-               ctx = ERR_PTR(-EINVAL);
-       else
-               idr_remove(&ctx_id_table, ctx->id);
-       up(&ctx_id_mutex);
-
-       if (IS_ERR(ctx))
-               return PTR_ERR(ctx);
-
-       atomic_dec(&ctx->ref);
-       wait_event(ctx->wait, !atomic_read(&ctx->ref));
+       return event == IB_CM_REQ_RECEIVED || event == IB_CM_SIDR_REQ_RECEIVED;
+}
 
-       /* No new events will be generated after destroying the cm_id. */
-       if (!IS_ERR(ctx->cm_id))
-               ib_destroy_cm_id(ctx->cm_id);
+static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx)
+{
+       struct ib_ucm_event *uevent;
 
-       /* Cleanup events not yet reported to the user. */
-       down(&file->mutex);
+       down(&ctx->file->mutex);
        list_del(&ctx->file_list);
        while (!list_empty(&ctx->events)) {
 
@@ -133,15 +115,12 @@ static ssize_t ib_ucm_destroy_ctx(struct ib_ucm_file *file, int id)
                list_del(&uevent->ctx_list);
 
                /* clear incoming connections. */
-               if (uevent->cm_id)
+               if (ib_ucm_new_cm_id(uevent->resp.event))
                        ib_destroy_cm_id(uevent->cm_id);
 
                kfree(uevent);
        }
-       up(&file->mutex);
-
-       kfree(ctx);
-       return 0;
+       up(&ctx->file->mutex);
 }
 
 static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -153,36 +132,31 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
        if (!ctx)
                return NULL;
 
+       memset(ctx, 0, sizeof *ctx);
        atomic_set(&ctx->ref, 1);
        init_waitqueue_head(&ctx->wait);
        ctx->file = file;
-
        INIT_LIST_HEAD(&ctx->events);
 
-       list_add_tail(&ctx->file_list, &file->ctxs);
-
-       ctx_id_rover = (ctx_id_rover + 1) & INT_MAX;
-retry:
-       result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
-       if (!result)
-               goto error;
+       do {
+               result = idr_pre_get(&ctx_id_table, GFP_KERNEL);
+               if (!result)
+                       goto error;
 
-       down(&ctx_id_mutex);
-       result = idr_get_new_above(&ctx_id_table, ctx, ctx_id_rover, &ctx->id);
-       up(&ctx_id_mutex);
+               down(&ctx_id_mutex);
+               result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
+               up(&ctx_id_mutex);
+       } while (result == -EAGAIN);
 
-       if (result == -EAGAIN)
-               goto retry;
        if (result)
                goto error;
 
+       list_add_tail(&ctx->file_list, &file->ctxs);
        ucm_dbg("Allocated CM ID <%d>\n", ctx->id);
-
        return ctx;
+
 error:
-       list_del(&ctx->file_list);
        kfree(ctx);
-
        return NULL;
 }
 /*
@@ -219,12 +193,9 @@ static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
                kpath->packet_life_time_selector;
 }
 
-static void ib_ucm_event_req_get(struct ib_ucm_context *ctx,
-                                struct ib_ucm_req_event_resp *ureq,
+static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
                                 struct ib_cm_req_event_param *kreq)
 {
-       ureq->listen_id = ctx->id;
-
        ureq->remote_ca_guid             = kreq->remote_ca_guid;
        ureq->remote_qkey                = kreq->remote_qkey;
        ureq->remote_qpn                 = kreq->remote_qpn;
@@ -259,14 +230,6 @@ static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
        urep->srq                 = krep->srq;
 }
 
-static void ib_ucm_event_sidr_req_get(struct ib_ucm_context *ctx,
-                                     struct ib_ucm_sidr_req_event_resp *ureq,
-                                     struct ib_cm_sidr_req_event_param *kreq)
-{
-       ureq->listen_id = ctx->id;
-       ureq->pkey      = kreq->pkey;
-}
-
 static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
                                      struct ib_cm_sidr_rep_event_param *krep)
 {
@@ -275,15 +238,14 @@ static void ib_ucm_event_sidr_rep_get(struct ib_ucm_sidr_rep_event_resp *urep,
        urep->qpn    = krep->qpn;
 };
 
-static int ib_ucm_event_process(struct ib_ucm_context *ctx,
-                               struct ib_cm_event *evt,
+static int ib_ucm_event_process(struct ib_cm_event *evt,
                                struct ib_ucm_event *uvt)
 {
        void *info = NULL;
 
        switch (evt->event) {
        case IB_CM_REQ_RECEIVED:
-               ib_ucm_event_req_get(ctx, &uvt->resp.u.req_resp,
+               ib_ucm_event_req_get(&uvt->resp.u.req_resp,
                                     &evt->param.req_rcvd);
                uvt->data_len      = IB_CM_REQ_PRIVATE_DATA_SIZE;
                uvt->resp.present  = IB_UCM_PRES_PRIMARY;
@@ -331,8 +293,8 @@ static int ib_ucm_event_process(struct ib_ucm_context *ctx,
                info          = evt->param.apr_rcvd.apr_info;
                break;
        case IB_CM_SIDR_REQ_RECEIVED:
-               ib_ucm_event_sidr_req_get(ctx, &uvt->resp.u.sidr_req_resp,
-                                         &evt->param.sidr_req_rcvd);
+               uvt->resp.u.sidr_req_resp.pkey = 
+                                       evt->param.sidr_req_rcvd.pkey;
                uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE;
                break;
        case IB_CM_SIDR_REP_RECEIVED:
@@ -378,31 +340,24 @@ static int ib_ucm_event_handler(struct ib_cm_id *cm_id,
        struct ib_ucm_event *uevent;
        struct ib_ucm_context *ctx;
        int result = 0;
-       int id;
 
        ctx = cm_id->context;
 
-       if (event->event == IB_CM_REQ_RECEIVED ||
-           event->event == IB_CM_SIDR_REQ_RECEIVED)
-               id = IB_UCM_CM_ID_INVALID;
-       else
-               id = ctx->id;
-
        uevent = kmalloc(sizeof(*uevent), GFP_KERNEL);
        if (!uevent)
                goto err1;
 
        memset(uevent, 0, sizeof(*uevent));
-       uevent->resp.id    = id;
+       uevent->ctx = ctx;
+       uevent->cm_id = cm_id;
+       uevent->resp.uid = ctx->uid;
+       uevent->resp.id = ctx->id;
        uevent->resp.event = event->event;
 
-       result = ib_ucm_event_process(ctx, event, uevent);
+       result = ib_ucm_event_process(event, uevent);
        if (result)
                goto err2;
 
-       uevent->ctx   = ctx;
-       uevent->cm_id = (id == IB_UCM_CM_ID_INVALID) ? cm_id : NULL;
-
        down(&ctx->file->mutex);
        list_add_tail(&uevent->file_list, &ctx->file->events);
        list_add_tail(&uevent->ctx_list, &ctx->events);
@@ -414,7 +369,7 @@ err2:
        kfree(uevent);
 err1:
        /* Destroy new cm_id's */
-       return (id == IB_UCM_CM_ID_INVALID);
+       return ib_ucm_new_cm_id(event->event);
 }
 
 static ssize_t ib_ucm_event(struct ib_ucm_file *file,
@@ -423,7 +378,7 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
 {
        struct ib_ucm_context *ctx;
        struct ib_ucm_event_get cmd;
-       struct ib_ucm_event *uevent = NULL;
+       struct ib_ucm_event *uevent;
        int result = 0;
        DEFINE_WAIT(wait);
 
@@ -436,7 +391,6 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
         * wait
         */
        down(&file->mutex);
-
        while (list_empty(&file->events)) {
 
                if (file->filp->f_flags & O_NONBLOCK) {
@@ -463,21 +417,18 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
 
        uevent = list_entry(file->events.next, struct ib_ucm_event, file_list);
 
-       if (!uevent->cm_id)
-               goto user;
+       if (ib_ucm_new_cm_id(uevent->resp.event)) {
+               ctx = ib_ucm_ctx_alloc(file);
+               if (!ctx) {
+                       result = -ENOMEM;
+                       goto done;
+               }
 
-       ctx = ib_ucm_ctx_alloc(file);
-       if (!ctx) {
-               result = -ENOMEM;
-               goto done;
+               ctx->cm_id = uevent->cm_id;
+               ctx->cm_id->context = ctx;
+               uevent->resp.id = ctx->id;
        }
 
-       ctx->cm_id          = uevent->cm_id;
-       ctx->cm_id->context = ctx;
-
-       uevent->resp.id = ctx->id;
-
-user:
        if (copy_to_user((void __user *)(unsigned long)cmd.response,
                         &uevent->resp, sizeof(uevent->resp))) {
                result = -EFAULT;
@@ -485,12 +436,10 @@ user:
        }
 
        if (uevent->data) {
-
                if (cmd.data_len < uevent->data_len) {
                        result = -ENOMEM;
                        goto done;
                }
-
                if (copy_to_user((void __user *)(unsigned long)cmd.data,
                                 uevent->data, uevent->data_len)) {
                        result = -EFAULT;
@@ -499,12 +448,10 @@ user:
        }
 
        if (uevent->info) {
-
                if (cmd.info_len < uevent->info_len) {
                        result = -ENOMEM;
                        goto done;
                }
-
                if (copy_to_user((void __user *)(unsigned long)cmd.info,
                                 uevent->info, uevent->info_len)) {
                        result = -EFAULT;
@@ -514,6 +461,7 @@ user:
 
        list_del(&uevent->file_list);
        list_del(&uevent->ctx_list);
+       uevent->ctx->events_reported++;
 
        kfree(uevent->data);
        kfree(uevent->info);
@@ -545,6 +493,7 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
        if (!ctx)
                return -ENOMEM;
 
+       ctx->uid = cmd.uid;
        ctx->cm_id = ib_create_cm_id(ib_ucm_event_handler, ctx);
        if (IS_ERR(ctx->cm_id)) {
                result = PTR_ERR(ctx->cm_id);
@@ -561,7 +510,14 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
        return 0;
 
 err:
-       ib_ucm_destroy_ctx(file, ctx->id);
+       down(&ctx_id_mutex);
+       idr_remove(&ctx_id_table, ctx->id);
+       up(&ctx_id_mutex);
+
+       if (!IS_ERR(ctx->cm_id))
+               ib_destroy_cm_id(ctx->cm_id);
+
+       kfree(ctx);
        return result;
 }
 
@@ -570,11 +526,44 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
                                 int in_len, int out_len)
 {
        struct ib_ucm_destroy_id cmd;
+       struct ib_ucm_destroy_id_resp resp;
+       struct ib_ucm_context *ctx;
+       int result = 0;
+
+       if (out_len < sizeof(resp))
+               return -ENOSPC;
 
        if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
                return -EFAULT;
 
-       return ib_ucm_destroy_ctx(file, cmd.id);
+       down(&ctx_id_mutex);
+       ctx = idr_find(&ctx_id_table, cmd.id);
+       if (!ctx)
+               ctx = ERR_PTR(-ENOENT);
+       else if (ctx->file != file)
+               ctx = ERR_PTR(-EINVAL);
+       else
+               idr_remove(&ctx_id_table, ctx->id);
+       up(&ctx_id_mutex);
+
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
+       atomic_dec(&ctx->ref);
+       wait_event(ctx->wait, !atomic_read(&ctx->ref));
+
+       /* No new events will be generated after destroying the cm_id. */
+       ib_destroy_cm_id(ctx->cm_id);
+       /* Cleanup events not yet reported to the user. */
+       ib_ucm_cleanup_events(ctx);
+
+       resp.events_reported = ctx->events_reported;
+       if (copy_to_user((void __user *)(unsigned long)cmd.response,
+                        &resp, sizeof(resp)))
+               result = -EFAULT;
+
+       kfree(ctx);
+       return result;
 }
 
 static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
@@ -609,6 +598,98 @@ static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file,
        return result;
 }
 
+static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr,
+                               struct ib_ah_attr *src_attr)
+{
+       memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw,
+              sizeof src_attr->grh.dgid);
+       dest_attr->grh_flow_label = src_attr->grh.flow_label;
+       dest_attr->grh_sgid_index = src_attr->grh.sgid_index;
+       dest_attr->grh_hop_limit = src_attr->grh.hop_limit;
+       dest_attr->grh_traffic_class = src_attr->grh.traffic_class;
+
+       dest_attr->dlid = src_attr->dlid;
+       dest_attr->sl = src_attr->sl;
+       dest_attr->src_path_bits = src_attr->src_path_bits;
+       dest_attr->static_rate = src_attr->static_rate;
+       dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH);
+       dest_attr->port_num = src_attr->port_num;
+}
+
+static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr,
+                               struct ib_qp_attr *src_attr)
+{
+       dest_attr->cur_qp_state = src_attr->cur_qp_state;
+       dest_attr->path_mtu = src_attr->path_mtu;
+       dest_attr->path_mig_state = src_attr->path_mig_state;
+       dest_attr->qkey = src_attr->qkey;
+       dest_attr->rq_psn = src_attr->rq_psn;
+       dest_attr->sq_psn = src_attr->sq_psn;
+       dest_attr->dest_qp_num = src_attr->dest_qp_num;
+       dest_attr->qp_access_flags = src_attr->qp_access_flags;
+
+       dest_attr->max_send_wr = src_attr->cap.max_send_wr;
+       dest_attr->max_recv_wr = src_attr->cap.max_recv_wr;
+       dest_attr->max_send_sge = src_attr->cap.max_send_sge;
+       dest_attr->max_recv_sge = src_attr->cap.max_recv_sge;
+       dest_attr->max_inline_data = src_attr->cap.max_inline_data;
+
+       ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr);
+       ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr);
+
+       dest_attr->pkey_index = src_attr->pkey_index;
+       dest_attr->alt_pkey_index = src_attr->alt_pkey_index;
+       dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify;
+       dest_attr->sq_draining = src_attr->sq_draining;
+       dest_attr->max_rd_atomic = src_attr->max_rd_atomic;
+       dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic;
+       dest_attr->min_rnr_timer = src_attr->min_rnr_timer;
+       dest_attr->port_num = src_attr->port_num;
+       dest_attr->timeout = src_attr->timeout;
+       dest_attr->retry_cnt = src_attr->retry_cnt;
+       dest_attr->rnr_retry = src_attr->rnr_retry;
+       dest_attr->alt_port_num = src_attr->alt_port_num;
+       dest_attr->alt_timeout = src_attr->alt_timeout;
+}
+
+static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
+                                  const char __user *inbuf,
+                                  int in_len, int out_len)
+{
+       struct ib_ucm_init_qp_attr_resp resp;
+       struct ib_ucm_init_qp_attr cmd;
+       struct ib_ucm_context *ctx;
+       struct ib_qp_attr qp_attr;
+       int result = 0;
+
+       if (out_len < sizeof(resp))
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
+               return -EFAULT;
+
+       ctx = ib_ucm_ctx_get(file, cmd.id);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
+       resp.qp_attr_mask = 0;
+       memset(&qp_attr, 0, sizeof qp_attr);
+       qp_attr.qp_state = cmd.qp_state;
+       result = ib_cm_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
+       if (result)
+               goto out;
+
+       ib_ucm_copy_qp_attr(&resp, &qp_attr);
+
+       if (copy_to_user((void __user *)(unsigned long)cmd.response,
+                        &resp, sizeof(resp)))
+               result = -EFAULT;
+
+out:
+       ib_ucm_ctx_put(ctx);
+       return result;
+}
+
 static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
                             const char __user *inbuf,
                             int in_len, int out_len)
@@ -808,6 +889,7 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
 
        ctx = ib_ucm_ctx_get(file, cmd.id);
        if (!IS_ERR(ctx)) {
+               ctx->uid = cmd.uid;
                result = ib_send_cm_rep(ctx->cm_id, &param);
                ib_ucm_ctx_put(ctx);
        } else
@@ -1086,6 +1168,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file,
        [IB_USER_CM_CMD_SEND_SIDR_REQ] = ib_ucm_send_sidr_req,
        [IB_USER_CM_CMD_SEND_SIDR_REP] = ib_ucm_send_sidr_rep,
        [IB_USER_CM_CMD_EVENT]         = ib_ucm_event,
+       [IB_USER_CM_CMD_INIT_QP_ATTR]  = ib_ucm_init_qp_attr,
 };
 
 static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
@@ -1161,12 +1244,18 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
 
        down(&file->mutex);
        while (!list_empty(&file->ctxs)) {
-
                ctx = list_entry(file->ctxs.next,
                                 struct ib_ucm_context, file_list);
-
                up(&file->mutex);
-               ib_ucm_destroy_ctx(file, ctx->id);
+
+               down(&ctx_id_mutex);
+               idr_remove(&ctx_id_table, ctx->id);
+               up(&ctx_id_mutex);
+
+               ib_destroy_cm_id(ctx->cm_id);
+               ib_ucm_cleanup_events(ctx);
+               kfree(ctx);
+
                down(&file->mutex);
        }
        up(&file->mutex);
index c8819b928a1ba82772d0ae48761ee41e7ebc6f4d..f46f37bc1201bdafae02dc16c9082ab0c1c983ab 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -43,8 +44,6 @@
 #include <rdma/ib_cm.h>
 #include <rdma/ib_user_cm.h>
 
-#define IB_UCM_CM_ID_INVALID 0xffffffff
-
 struct ib_ucm_file {
        struct semaphore mutex;
        struct file *filp;
@@ -58,9 +57,11 @@ struct ib_ucm_context {
        int                 id;
        wait_queue_head_t   wait;
        atomic_t            ref;
+       int                 events_reported;
 
        struct ib_ucm_file *file;
        struct ib_cm_id    *cm_id;
+       __u64              uid;
 
        struct list_head    events;    /* list of pending events. */
        struct list_head    file_list; /* member in file ctx list */
@@ -71,16 +72,12 @@ struct ib_ucm_event {
        struct list_head file_list; /* member in file event list */
        struct list_head ctx_list;  /* member in ctx event list */
 
+       struct ib_cm_id *cm_id;
        struct ib_ucm_event_resp resp;
        void *data;
        void *info;
        int data_len;
        int info_len;
-       /*
-        * new connection identifiers needs to be saved until
-        * userspace can get a handle on them.
-        */
-       struct ib_cm_id *cm_id;
 };
 
 #endif /* UCM_H */
index 180b3d4765e40bc4eae9d3c0c6516006fefdbee2..b1897bed14ad40174b834b359419f9a87f2ff6e5 100644 (file)
@@ -76,20 +76,28 @@ struct ib_uverbs_file {
        struct ib_uverbs_event_file             comp_file[1];
 };
 
-struct ib_uverbs_async_event {
-       struct ib_uverbs_async_event_desc       desc;
+struct ib_uverbs_event {
+       union {
+               struct ib_uverbs_async_event_desc       async;
+               struct ib_uverbs_comp_event_desc        comp;
+       }                                       desc;
        struct list_head                        list;
+       struct list_head                        obj_list;
+       u32                                    *counter;
 };
 
-struct ib_uverbs_comp_event {
-       struct ib_uverbs_comp_event_desc        desc;
-       struct list_head                        list;
+struct ib_uevent_object {
+       struct ib_uobject       uobject;
+       struct list_head        event_list;
+       u32                     events_reported;
 };
 
-struct ib_uobject_mr {
-       struct ib_uobject                       uobj;
-       struct page                            *page_list;
-       struct scatterlist                     *sg_list;
+struct ib_ucq_object {
+       struct ib_uobject       uobject;
+       struct list_head        comp_list;
+       struct list_head        async_list;
+       u32                     comp_events_reported;
+       u32                     async_events_reported;
 };
 
 extern struct semaphore ib_uverbs_idr_mutex;
index ebccf9f38af946e6cfb1c894ecf020f4c96aaae8..e91ebde4648105d57be74e907e767f60663f37bb 100644 (file)
@@ -590,7 +590,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        struct ib_uverbs_create_cq      cmd;
        struct ib_uverbs_create_cq_resp resp;
        struct ib_udata                 udata;
-       struct ib_uobject              *uobj;
+       struct ib_ucq_object           *uobj;
        struct ib_cq                   *cq;
        int                             ret;
 
@@ -611,8 +611,12 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        if (!uobj)
                return -ENOMEM;
 
-       uobj->user_handle = cmd.user_handle;
-       uobj->context     = file->ucontext;
+       uobj->uobject.user_handle   = cmd.user_handle;
+       uobj->uobject.context       = file->ucontext;
+       uobj->comp_events_reported  = 0;
+       uobj->async_events_reported = 0;
+       INIT_LIST_HEAD(&uobj->comp_list);
+       INIT_LIST_HEAD(&uobj->async_list);
 
        cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
                                             file->ucontext, &udata);
@@ -622,7 +626,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
        }
 
        cq->device        = file->device->ib_dev;
-       cq->uobject       = uobj;
+       cq->uobject       = &uobj->uobject;
        cq->comp_handler  = ib_uverbs_comp_handler;
        cq->event_handler = ib_uverbs_cq_event_handler;
        cq->cq_context    = file;
@@ -635,7 +639,7 @@ retry:
        }
 
        down(&ib_uverbs_idr_mutex);
-       ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->id);
+       ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
        up(&ib_uverbs_idr_mutex);
 
        if (ret == -EAGAIN)
@@ -644,11 +648,11 @@ retry:
                goto err_cq;
 
        spin_lock_irq(&file->ucontext->lock);
-       list_add_tail(&uobj->list, &file->ucontext->cq_list);
+       list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
        spin_unlock_irq(&file->ucontext->lock);
 
        memset(&resp, 0, sizeof resp);
-       resp.cq_handle = uobj->id;
+       resp.cq_handle = uobj->uobject.id;
        resp.cqe       = cq->cqe;
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -661,11 +665,11 @@ retry:
 
 err_list:
        spin_lock_irq(&file->ucontext->lock);
-       list_del(&uobj->list);
+       list_del(&uobj->uobject.list);
        spin_unlock_irq(&file->ucontext->lock);
 
        down(&ib_uverbs_idr_mutex);
-       idr_remove(&ib_uverbs_cq_idr, uobj->id);
+       idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
        up(&ib_uverbs_idr_mutex);
 
 err_cq:
@@ -680,21 +684,27 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
                             const char __user *buf, int in_len,
                             int out_len)
 {
-       struct ib_uverbs_destroy_cq cmd;
-       struct ib_cq               *cq;
-       struct ib_uobject          *uobj;
-       int                         ret = -EINVAL;
+       struct ib_uverbs_destroy_cq      cmd;
+       struct ib_uverbs_destroy_cq_resp resp;
+       struct ib_cq                    *cq;
+       struct ib_ucq_object            *uobj;
+       struct ib_uverbs_event          *evt, *tmp;
+       u64                              user_handle;
+       int                              ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
+       memset(&resp, 0, sizeof resp);
+
        down(&ib_uverbs_idr_mutex);
 
        cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
        if (!cq || cq->uobject->context != file->ucontext)
                goto out;
 
-       uobj = cq->uobject;
+       user_handle = cq->uobject->user_handle;
+       uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
 
        ret = ib_destroy_cq(cq);
        if (ret)
@@ -703,11 +713,32 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
        idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
 
        spin_lock_irq(&file->ucontext->lock);
-       list_del(&uobj->list);
+       list_del(&uobj->uobject.list);
        spin_unlock_irq(&file->ucontext->lock);
 
+       spin_lock_irq(&file->comp_file[0].lock);
+       list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+       spin_unlock_irq(&file->comp_file[0].lock);
+
+       spin_lock_irq(&file->async_file.lock);
+       list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+       spin_unlock_irq(&file->async_file.lock);
+
+       resp.comp_events_reported  = uobj->comp_events_reported;
+       resp.async_events_reported = uobj->async_events_reported;
+
        kfree(uobj);
 
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
 out:
        up(&ib_uverbs_idr_mutex);
 
@@ -721,7 +752,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        struct ib_uverbs_create_qp      cmd;
        struct ib_uverbs_create_qp_resp resp;
        struct ib_udata                 udata;
-       struct ib_uobject              *uobj;
+       struct ib_uevent_object        *uobj;
        struct ib_pd                   *pd;
        struct ib_cq                   *scq, *rcq;
        struct ib_srq                  *srq;
@@ -772,8 +803,10 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        attr.cap.max_recv_sge    = cmd.max_recv_sge;
        attr.cap.max_inline_data = cmd.max_inline_data;
 
-       uobj->user_handle = cmd.user_handle;
-       uobj->context     = file->ucontext;
+       uobj->uobject.user_handle = cmd.user_handle;
+       uobj->uobject.context     = file->ucontext;
+       uobj->events_reported     = 0;
+       INIT_LIST_HEAD(&uobj->event_list);
 
        qp = pd->device->create_qp(pd, &attr, &udata);
        if (IS_ERR(qp)) {
@@ -786,7 +819,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
        qp->send_cq       = attr.send_cq;
        qp->recv_cq       = attr.recv_cq;
        qp->srq           = attr.srq;
-       qp->uobject       = uobj;
+       qp->uobject       = &uobj->uobject;
        qp->event_handler = attr.event_handler;
        qp->qp_context    = attr.qp_context;
        qp->qp_type       = attr.qp_type;
@@ -805,17 +838,17 @@ retry:
                goto err_destroy;
        }
 
-       ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->id);
+       ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id);
 
        if (ret == -EAGAIN)
                goto retry;
        if (ret)
                goto err_destroy;
 
-       resp.qp_handle = uobj->id;
+       resp.qp_handle = uobj->uobject.id;
 
        spin_lock_irq(&file->ucontext->lock);
-       list_add_tail(&uobj->list, &file->ucontext->qp_list);
+       list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);
        spin_unlock_irq(&file->ucontext->lock);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -830,7 +863,7 @@ retry:
 
 err_list:
        spin_lock_irq(&file->ucontext->lock);
-       list_del(&uobj->list);
+       list_del(&uobj->uobject.list);
        spin_unlock_irq(&file->ucontext->lock);
 
 err_destroy:
@@ -930,21 +963,25 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
                             const char __user *buf, int in_len,
                             int out_len)
 {
-       struct ib_uverbs_destroy_qp cmd;
-       struct ib_qp               *qp;
-       struct ib_uobject          *uobj;
-       int                         ret = -EINVAL;
+       struct ib_uverbs_destroy_qp      cmd;
+       struct ib_uverbs_destroy_qp_resp resp;
+       struct ib_qp                    *qp;
+       struct ib_uevent_object         *uobj;
+       struct ib_uverbs_event          *evt, *tmp;
+       int                              ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
+       memset(&resp, 0, sizeof resp);
+
        down(&ib_uverbs_idr_mutex);
 
        qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
        if (!qp || qp->uobject->context != file->ucontext)
                goto out;
 
-       uobj = qp->uobject;
+       uobj = container_of(qp->uobject, struct ib_uevent_object, uobject);
 
        ret = ib_destroy_qp(qp);
        if (ret)
@@ -953,11 +990,24 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
        idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
 
        spin_lock_irq(&file->ucontext->lock);
-       list_del(&uobj->list);
+       list_del(&uobj->uobject.list);
        spin_unlock_irq(&file->ucontext->lock);
 
+       spin_lock_irq(&file->async_file.lock);
+       list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+       spin_unlock_irq(&file->async_file.lock);
+
+       resp.events_reported = uobj->events_reported;
+
        kfree(uobj);
 
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
 out:
        up(&ib_uverbs_idr_mutex);
 
@@ -1015,7 +1065,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        struct ib_uverbs_create_srq      cmd;
        struct ib_uverbs_create_srq_resp resp;
        struct ib_udata                  udata;
-       struct ib_uobject               *uobj;
+       struct ib_uevent_object         *uobj;
        struct ib_pd                    *pd;
        struct ib_srq                   *srq;
        struct ib_srq_init_attr          attr;
@@ -1050,8 +1100,10 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
        attr.attr.max_sge   = cmd.max_sge;
        attr.attr.srq_limit = cmd.srq_limit;
 
-       uobj->user_handle = cmd.user_handle;
-       uobj->context     = file->ucontext;
+       uobj->uobject.user_handle = cmd.user_handle;
+       uobj->uobject.context     = file->ucontext;
+       uobj->events_reported     = 0;
+       INIT_LIST_HEAD(&uobj->event_list);
 
        srq = pd->device->create_srq(pd, &attr, &udata);
        if (IS_ERR(srq)) {
@@ -1061,7 +1113,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
 
        srq->device        = pd->device;
        srq->pd            = pd;
-       srq->uobject       = uobj;
+       srq->uobject       = &uobj->uobject;
        srq->event_handler = attr.event_handler;
        srq->srq_context   = attr.srq_context;
        atomic_inc(&pd->usecnt);
@@ -1075,17 +1127,17 @@ retry:
                goto err_destroy;
        }
 
-       ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->id);
+       ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
 
        if (ret == -EAGAIN)
                goto retry;
        if (ret)
                goto err_destroy;
 
-       resp.srq_handle = uobj->id;
+       resp.srq_handle = uobj->uobject.id;
 
        spin_lock_irq(&file->ucontext->lock);
-       list_add_tail(&uobj->list, &file->ucontext->srq_list);
+       list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
        spin_unlock_irq(&file->ucontext->lock);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
@@ -1100,7 +1152,7 @@ retry:
 
 err_list:
        spin_lock_irq(&file->ucontext->lock);
-       list_del(&uobj->list);
+       list_del(&uobj->uobject.list);
        spin_unlock_irq(&file->ucontext->lock);
 
 err_destroy:
@@ -1149,21 +1201,25 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
                              const char __user *buf, int in_len,
                              int out_len)
 {
-       struct ib_uverbs_destroy_srq cmd;
-       struct ib_srq               *srq;
-       struct ib_uobject           *uobj;
-       int                          ret = -EINVAL;
+       struct ib_uverbs_destroy_srq      cmd;
+       struct ib_uverbs_destroy_srq_resp resp;
+       struct ib_srq                    *srq;
+       struct ib_uevent_object          *uobj;
+       struct ib_uverbs_event           *evt, *tmp;
+       int                               ret = -EINVAL;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
 
        down(&ib_uverbs_idr_mutex);
 
+       memset(&resp, 0, sizeof resp);
+
        srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
        if (!srq || srq->uobject->context != file->ucontext)
                goto out;
 
-       uobj = srq->uobject;
+       uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
 
        ret = ib_destroy_srq(srq);
        if (ret)
@@ -1172,11 +1228,24 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
        idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
 
        spin_lock_irq(&file->ucontext->lock);
-       list_del(&uobj->list);
+       list_del(&uobj->uobject.list);
        spin_unlock_irq(&file->ucontext->lock);
 
+       spin_lock_irq(&file->async_file.lock);
+       list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {
+               list_del(&evt->list);
+               kfree(evt);
+       }
+       spin_unlock_irq(&file->async_file.lock);
+
+       resp.events_reported = uobj->events_reported;
+
        kfree(uobj);
 
+       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+                        &resp, sizeof resp))
+               ret = -EFAULT;
+
 out:
        up(&ib_uverbs_idr_mutex);
 
index 09caf5b1ef36131305bc02171672cc39550d777b..ce5bdb7af3063408f488e4a85d59caa4edfe01a7 100644 (file)
@@ -120,7 +120,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
                idr_remove(&ib_uverbs_qp_idr, uobj->id);
                ib_destroy_qp(qp);
                list_del(&uobj->list);
-               kfree(uobj);
+               kfree(container_of(uobj, struct ib_uevent_object, uobject));
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
@@ -128,7 +128,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
                idr_remove(&ib_uverbs_cq_idr, uobj->id);
                ib_destroy_cq(cq);
                list_del(&uobj->list);
-               kfree(uobj);
+               kfree(container_of(uobj, struct ib_ucq_object, uobject));
        }
 
        list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
@@ -136,7 +136,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
                idr_remove(&ib_uverbs_srq_idr, uobj->id);
                ib_destroy_srq(srq);
                list_del(&uobj->list);
-               kfree(uobj);
+               kfree(container_of(uobj, struct ib_uevent_object, uobject));
        }
 
        /* XXX Free MWs */
@@ -182,7 +182,7 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
                                    size_t count, loff_t *pos)
 {
        struct ib_uverbs_event_file *file = filp->private_data;
-       void *event;
+       struct ib_uverbs_event *event;
        int eventsz;
        int ret = 0;
 
@@ -207,21 +207,23 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
                return -ENODEV;
        }
 
-       if (file->is_async) {
-               event   = list_entry(file->event_list.next,
-                                    struct ib_uverbs_async_event, list);
+       event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
+
+       if (file->is_async)
                eventsz = sizeof (struct ib_uverbs_async_event_desc);
-       } else {
-               event   = list_entry(file->event_list.next,
-                                    struct ib_uverbs_comp_event, list);
+       else
                eventsz = sizeof (struct ib_uverbs_comp_event_desc);
-       }
 
        if (eventsz > count) {
                ret   = -EINVAL;
                event = NULL;
-       } else
+       } else {
                list_del(file->event_list.next);
+               if (event->counter) {
+                       ++(*event->counter);
+                       list_del(&event->obj_list);
+               }
+       }
 
        spin_unlock_irq(&file->lock);
 
@@ -257,16 +259,13 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
 
 static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
 {
-       struct list_head *entry, *tmp;
+       struct ib_uverbs_event *entry, *tmp;
 
        spin_lock_irq(&file->lock);
        if (file->fd != -1) {
                file->fd = -1;
-               list_for_each_safe(entry, tmp, &file->event_list)
-                       if (file->is_async)
-                               kfree(list_entry(entry, struct ib_uverbs_async_event, list));
-                       else
-                               kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
+               list_for_each_entry_safe(entry, tmp, &file->event_list, list)
+                       kfree(entry);
        }
        spin_unlock_irq(&file->lock);
 }
@@ -304,18 +303,23 @@ static struct file_operations uverbs_event_fops = {
 
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
 {
-       struct ib_uverbs_file       *file = cq_context;
-       struct ib_uverbs_comp_event *entry;
-       unsigned long                flags;
+       struct ib_uverbs_file  *file = cq_context;
+       struct ib_ucq_object   *uobj;
+       struct ib_uverbs_event *entry;
+       unsigned long           flags;
 
        entry = kmalloc(sizeof *entry, GFP_ATOMIC);
        if (!entry)
                return;
 
-       entry->desc.cq_handle = cq->uobject->user_handle;
+       uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
+
+       entry->desc.comp.cq_handle = cq->uobject->user_handle;
+       entry->counter             = &uobj->comp_events_reported;
 
        spin_lock_irqsave(&file->comp_file[0].lock, flags);
        list_add_tail(&entry->list, &file->comp_file[0].event_list);
+       list_add_tail(&entry->obj_list, &uobj->comp_list);
        spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
 
        wake_up_interruptible(&file->comp_file[0].poll_wait);
@@ -323,20 +327,25 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
 }
 
 static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
-                                   __u64 element, __u64 event)
+                                   __u64 element, __u64 event,
+                                   struct list_head *obj_list,
+                                   u32 *counter)
 {
-       struct ib_uverbs_async_event *entry;
+       struct ib_uverbs_event *entry;
        unsigned long flags;
 
        entry = kmalloc(sizeof *entry, GFP_ATOMIC);
        if (!entry)
                return;
 
-       entry->desc.element    = element;
-       entry->desc.event_type = event;
+       entry->desc.async.element    = element;
+       entry->desc.async.event_type = event;
+       entry->counter               = counter;
 
        spin_lock_irqsave(&file->async_file.lock, flags);
        list_add_tail(&entry->list, &file->async_file.event_list);
+       if (obj_list)
+               list_add_tail(&entry->obj_list, obj_list);
        spin_unlock_irqrestore(&file->async_file.lock, flags);
 
        wake_up_interruptible(&file->async_file.poll_wait);
@@ -345,23 +354,39 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
 
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
 {
-       ib_uverbs_async_handler(context_ptr,
-                               event->element.cq->uobject->user_handle,
-                               event->event);
+       struct ib_ucq_object *uobj;
+
+       uobj = container_of(event->element.cq->uobject,
+                           struct ib_ucq_object, uobject);
+
+       ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+                               event->event, &uobj->async_list,
+                               &uobj->async_events_reported);
+                               
 }
 
 void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
 {
-       ib_uverbs_async_handler(context_ptr,
-                               event->element.qp->uobject->user_handle,
-                               event->event);
+       struct ib_uevent_object *uobj;
+
+       uobj = container_of(event->element.qp->uobject,
+                           struct ib_uevent_object, uobject);
+
+       ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+                               event->event, &uobj->event_list,
+                               &uobj->events_reported);
 }
 
 void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
 {
-       ib_uverbs_async_handler(context_ptr,
-                               event->element.srq->uobject->user_handle,
-                               event->event);
+       struct ib_uevent_object *uobj;
+
+       uobj = container_of(event->element.srq->uobject,
+                           struct ib_uevent_object, uobject);
+
+       ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+                               event->event, &uobj->event_list,
+                               &uobj->events_reported);
 }
 
 static void ib_uverbs_event_handler(struct ib_event_handler *handler,
@@ -370,7 +395,8 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
        struct ib_uverbs_file *file =
                container_of(handler, struct ib_uverbs_file, event_handler);
 
-       ib_uverbs_async_handler(file, event->element.port_num, event->event);
+       ib_uverbs_async_handler(file, event->element.port_num, event->event,
+                               NULL, NULL);
 }
 
 static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,
index 0164b84d4ec643062892122cf6ebf567d92ec5f1..bcef06bf15e724c47aaedd013168be2bf9fe7d63 100644 (file)
@@ -220,6 +220,16 @@ static void *get_send_wqe(struct mthca_qp *qp, int n)
                         (PAGE_SIZE - 1));
 }
 
+static void mthca_wq_init(struct mthca_wq *wq)
+{
+       spin_lock_init(&wq->lock);
+       wq->next_ind  = 0;
+       wq->last_comp = wq->max - 1;
+       wq->head      = 0;
+       wq->tail      = 0;
+       wq->last      = NULL;
+}
+
 void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
                    enum ib_event_type event_type)
 {
@@ -833,8 +843,8 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                store_attrs(to_msqp(qp), attr, attr_mask);
 
        /*
-        * If we are moving QP0 to RTR, bring the IB link up; if we
-        * are moving QP0 to RESET or ERROR, bring the link back down.
+        * If we moved QP0 to RTR, bring the IB link up; if we moved
+        * QP0 to RESET or ERROR, bring the link back down.
         */
        if (is_qp0(dev, qp)) {
                if (cur_state != IB_QPS_RTR &&
@@ -848,6 +858,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
                        mthca_CLOSE_IB(dev, to_msqp(qp)->port, &status);
        }
 
+       /*
+        * If we moved a kernel QP to RESET, clean up all old CQ
+        * entries and reinitialize the QP.
+        */
+       if (!err && new_state == IB_QPS_RESET && !qp->ibqp.uobject) {
+               mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq)->cqn, qp->qpn,
+                              qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+               if (qp->ibqp.send_cq != qp->ibqp.recv_cq)
+                       mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq)->cqn, qp->qpn,
+                                      qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
+
+               mthca_wq_init(&qp->sq);
+               mthca_wq_init(&qp->rq);
+
+               if (mthca_is_memfree(dev)) {
+                       *qp->sq.db = 0;
+                       *qp->rq.db = 0;
+               }
+       }
+
        return err;
 }
 
@@ -1003,16 +1033,6 @@ static void mthca_free_memfree(struct mthca_dev *dev,
        }
 }
 
-static void mthca_wq_init(struct mthca_wq* wq)
-{
-       spin_lock_init(&wq->lock);
-       wq->next_ind  = 0;
-       wq->last_comp = wq->max - 1;
-       wq->head      = 0;
-       wq->tail      = 0;
-       wq->last      = NULL;
-}
-
 static int mthca_alloc_qp_common(struct mthca_dev *dev,
                                 struct mthca_pd *pd,
                                 struct mthca_cq *send_cq,
@@ -1024,6 +1044,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
        int i;
 
        atomic_set(&qp->refcount, 1);
+       init_waitqueue_head(&qp->wait);
        qp->state        = IB_QPS_RESET;
        qp->atomic_rd_en = 0;
        qp->resp_depth   = 0;
index 0e8ac138e355bd4c71e2c21f58a809eb7d0f190e..49d120d2b92c5308e5dda9fe802a4ae9667b26ac 100644 (file)
@@ -1062,6 +1062,8 @@ static void ipoib_remove_one(struct ib_device *device)
                ipoib_dev_cleanup(priv->dev);
                free_netdev(priv->dev);
        }
+
+       kfree(dev_list);
 }
 
 static int __init ipoib_init_module(void)
index 19c14c4beb44e2537b2207435e5a625efb9a5f2f..3738d173f9a65a43e3d075294f00d6f07851ecab 100644 (file)
@@ -322,7 +322,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
                        if (get_user(v, ip + 1)) return -EFAULT;
                        if (v < 0 || v > KEY_MAX) return -EINVAL;
-                       if (v >> (dev->keycodesize * 8)) return -EINVAL;
+                       if (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
                        u = SET_INPUT_KEYCODE(dev, t, v);
                        clear_bit(u, dev->keybit);
                        set_bit(v, dev->keybit);
@@ -509,7 +509,7 @@ do { \
        int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
        if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
        for (i = 0; i < len / sizeof(compat_long_t); i++) \
-               if (copy_to_user((compat_long_t*) p + i, \
+               if (copy_to_user((compat_long_t __user *) p + i, \
                                 (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
                                 sizeof(compat_long_t))) \
                        return -EFAULT; \
index 58728ebaaf80ccc33b31770af4e77a7d824a7299..e5a31e55d3e2474d7d0af423790f27c8b5b86a83 100644 (file)
@@ -249,9 +249,6 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data,
 
 int iforce_get_id_packet(struct iforce *iforce, char *packet)
 {
-       DECLARE_WAITQUEUE(wait, current);
-       int timeout = HZ; /* 1 second */
-
        switch (iforce->bus) {
 
        case IFORCE_USB:
@@ -260,22 +257,13 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
                iforce->cr.bRequest = packet[0];
                iforce->ctrl->dev = iforce->usbdev;
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               add_wait_queue(&iforce->wait, &wait);
-
-               if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&iforce->wait, &wait);
+               if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC))
                        return -1;
-               }
 
-               while (timeout && iforce->ctrl->status == -EINPROGRESS)
-                       timeout = schedule_timeout(timeout);
+               wait_event_interruptible_timeout(iforce->wait,
+                       iforce->ctrl->status != -EINPROGRESS, HZ);
 
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&iforce->wait, &wait);
-
-               if (!timeout) {
+               if (iforce->ctrl->status != -EINPROGRESS) {
                        usb_unlink_urb(iforce->ctrl);
                        return -1;
                }
@@ -290,16 +278,10 @@ int iforce_get_id_packet(struct iforce *iforce, char *packet)
                iforce->expect_packet = FF_CMD_QUERY;
                iforce_send_packet(iforce, FF_CMD_QUERY, packet);
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               add_wait_queue(&iforce->wait, &wait);
-
-               while (timeout && iforce->expect_packet)
-                       timeout = schedule_timeout(timeout);
-
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&iforce->wait, &wait);
+               wait_event_interruptible_timeout(iforce->wait,
+                       !iforce->expect_packet, HZ);
 
-               if (!timeout) {
+               if (iforce->expect_packet) {
                        iforce->expect_packet = 0;
                        return -1;
                }
index 6369a24684fe35eb1d25ed98a384c902197ad76b..58600f91eff5212b6464d3843e367b482fd09c75 100644 (file)
@@ -95,6 +95,7 @@ static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
                goto exit;
        }
 
+       wake_up(&iforce->wait);
        iforce_process_packet(iforce,
                (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
 
index 4d4985b59abf182887349fedd73e758d9986102d..1ad8c2ee7dbf337b4417e93cfcf158a42895700a 100644 (file)
@@ -208,6 +208,7 @@ struct atkbd {
        unsigned char resend;
        unsigned char release;
        unsigned char bat_xl;
+       unsigned char err_xl;
        unsigned int last;
        unsigned long time;
 };
@@ -296,15 +297,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
                if (atkbd->emul ||
                    !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 ||
                      code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA ||
-                     code == ATKBD_RET_ERR ||
+                    (code == ATKBD_RET_ERR && !atkbd->err_xl) ||
                     (code == ATKBD_RET_BAT && !atkbd->bat_xl))) {
                        atkbd->release = code >> 7;
                        code &= 0x7f;
                }
 
-               if (!atkbd->emul &&
-                    (code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
+               if (!atkbd->emul) {
+                    if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
                        atkbd->bat_xl = !atkbd->release;
+                    if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
+                       atkbd->err_xl = !atkbd->release;
+               }
        }
 
        switch (code) {
index 596964ceb96dc39b0351ff386fa539351aeb6a10..4bae5d89348d7d798169b73be559e3f0215a6220 100644 (file)
@@ -44,7 +44,7 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static unsigned char sunkbd_keycode[128] = {
-         0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,  0,
+         0,128,114,129,115, 59, 60, 68, 61, 87, 62, 88, 63,100, 64,112,
         65, 66, 67, 56,103,119, 99, 70,105,130,131,108,106,  1,  2,  3,
          4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 41, 14,110,113, 98, 55,
        116,132, 83,133,102, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
index c4909b49337d23e708e4e4850c1e69ac1f1488b7..82b330bbf068d27a94764fd1af5bc4975ed1d4fb 100644 (file)
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL)    += sermouse.o
 obj-$(CONFIG_MOUSE_HIL)                += hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)    += vsxxxaa.o
 
-psmouse-objs  := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
+psmouse-objs  := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o trackpoint.o
index 0d68e5e0182aea89825963b8fc87b291ae320fd9..b20783f9748adbdad1be653abfd83dbec4448b1e 100644 (file)
@@ -170,7 +170,7 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
        input_report_key(dev, BTN_TOOL_FINGER, z > 0);
 
        if (priv->i->flags & ALPS_WHEEL)
-               input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
+               input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
 
        if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
                input_report_key(dev, BTN_FORWARD, forward);
index 48d2b20d264299b30cd6cac8441ecab38253c1d4..7df96525222e5dc6a2fc2ba6aea9a332023b4558 100644 (file)
@@ -150,12 +150,12 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr
        ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
 }
 
-static ssize_t psmouse_attr_show_smartscroll(struct psmouse *psmouse, char *buf)
+static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf)
 {
        return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0);
 }
 
-static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        unsigned long value;
        char *rest;
@@ -169,7 +169,8 @@ static ssize_t psmouse_attr_set_smartscroll(struct psmouse *psmouse, const char
        return count;
 }
 
-PSMOUSE_DEFINE_ATTR(smartscroll);
+PSMOUSE_DEFINE_ATTR(smartscroll, S_IWUSR | S_IRUGO, NULL,
+                       ps2pp_attr_show_smartscroll, ps2pp_attr_set_smartscroll);
 
 /*
  * Support 800 dpi resolution _only_ if the user wants it (there are good
@@ -194,7 +195,7 @@ static void ps2pp_set_resolution(struct psmouse *psmouse, unsigned int resolutio
 
 static void ps2pp_disconnect(struct psmouse *psmouse)
 {
-       device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
+       device_remove_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll.dattr);
 }
 
 static struct ps2pp_info *get_model_info(unsigned char model)
@@ -222,6 +223,7 @@ static struct ps2pp_info *get_model_info(unsigned char model)
                { 80,   PS2PP_KIND_WHEEL,       PS2PP_SIDE_BTN | PS2PP_WHEEL },
                { 81,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 83,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
+               { 86,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 88,   PS2PP_KIND_WHEEL,       PS2PP_WHEEL },
                { 96,   0,                      0 },
                { 97,   PS2PP_KIND_TP3,         PS2PP_WHEEL | PS2PP_HWHEEL },
@@ -379,7 +381,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
                                psmouse->set_resolution = ps2pp_set_resolution;
                                psmouse->disconnect = ps2pp_disconnect;
 
-                               device_create_file(&psmouse->ps2dev.serio->dev, &psmouse_attr_smartscroll);
+                               device_create_file(&psmouse->ps2dev.serio->dev,
+                                                  &psmouse_attr_smartscroll.dattr);
                        }
                }
 
index 12bdd3eff923ea32042d76f47110d217c43243f7..af24313ff5bb14973c5fdaa9bcbfcd5dc0f66dae 100644 (file)
@@ -25,6 +25,7 @@
 #include "logips2pp.h"
 #include "alps.h"
 #include "lifebook.h"
+#include "trackpoint.h"
 
 #define DRIVER_DESC    "PS/2 mouse driver"
 
@@ -57,10 +58,30 @@ static unsigned int psmouse_resetafter;
 module_param_named(resetafter, psmouse_resetafter, uint, 0644);
 MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
 
-PSMOUSE_DEFINE_ATTR(protocol);
-PSMOUSE_DEFINE_ATTR(rate);
-PSMOUSE_DEFINE_ATTR(resolution);
-PSMOUSE_DEFINE_ATTR(resetafter);
+PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
+                       NULL,
+                       psmouse_attr_show_protocol, psmouse_attr_set_protocol);
+PSMOUSE_DEFINE_ATTR(rate, S_IWUSR | S_IRUGO,
+                       (void *) offsetof(struct psmouse, rate),
+                       psmouse_show_int_attr, psmouse_attr_set_rate);
+PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
+                       (void *) offsetof(struct psmouse, resolution),
+                       psmouse_show_int_attr, psmouse_attr_set_resolution);
+PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
+                       (void *) offsetof(struct psmouse, resetafter),
+                       psmouse_show_int_attr, psmouse_set_int_attr);
+
+static struct attribute *psmouse_attributes[] = {
+       &psmouse_attr_protocol.dattr.attr,
+       &psmouse_attr_rate.dattr.attr,
+       &psmouse_attr_resolution.dattr.attr,
+       &psmouse_attr_resetafter.dattr.attr,
+       NULL
+};
+
+static struct attribute_group psmouse_attribute_group = {
+       .attrs  = psmouse_attributes,
+};
 
 __obsolete_setup("psmouse_noext");
 __obsolete_setup("psmouse_resolution=");
@@ -519,6 +540,12 @@ static int psmouse_extensions(struct psmouse *psmouse,
        if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
                return PSMOUSE_IMPS;
 
+/*
+ * Try to initialize the IBM TrackPoint
+ */
+       if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
+               return PSMOUSE_TRACKPOINT;
+
 /*
  * Okay, all failed, we have a standard mouse here. The number of the buttons
  * is still a question, though. We assume 3.
@@ -599,6 +626,12 @@ static struct psmouse_protocol psmouse_protocols[] = {
                .alias          = "lifebook",
                .init           = lifebook_init,
        },
+       {
+               .type           = PSMOUSE_TRACKPOINT,
+               .name           = "TPPS/2",
+               .alias          = "trackpoint",
+               .detect         = trackpoint_detect,
+       },
        {
                .type           = PSMOUSE_AUTO,
                .name           = "auto",
@@ -787,10 +820,7 @@ static void psmouse_disconnect(struct serio *serio)
 
        psmouse = serio_get_drvdata(serio);
 
-       device_remove_file(&serio->dev, &psmouse_attr_protocol);
-       device_remove_file(&serio->dev, &psmouse_attr_rate);
-       device_remove_file(&serio->dev, &psmouse_attr_resolution);
-       device_remove_file(&serio->dev, &psmouse_attr_resetafter);
+       sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
 
        down(&psmouse_sem);
 
@@ -927,10 +957,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
        if (parent && parent->pt_activate)
                parent->pt_activate(parent);
 
-       device_create_file(&serio->dev, &psmouse_attr_protocol);
-       device_create_file(&serio->dev, &psmouse_attr_rate);
-       device_create_file(&serio->dev, &psmouse_attr_resolution);
-       device_create_file(&serio->dev, &psmouse_attr_resetafter);
+       sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
 
        psmouse_activate(psmouse);
 
@@ -1027,10 +1054,12 @@ static struct serio_driver psmouse_drv = {
        .cleanup        = psmouse_cleanup,
 };
 
-ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
-                                ssize_t (*handler)(struct psmouse *, char *))
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *devattr,
+                                char *buf)
 {
        struct serio *serio = to_serio_port(dev);
+       struct psmouse_attribute *attr = to_psmouse_attr(devattr);
+       struct psmouse *psmouse;
        int retval;
 
        retval = serio_pin_driver(serio);
@@ -1042,19 +1071,21 @@ ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
                goto out;
        }
 
-       retval = handler(serio_get_drvdata(serio), buf);
+       psmouse = serio_get_drvdata(serio);
+
+       retval = attr->show(psmouse, attr->data, buf);
 
 out:
        serio_unpin_driver(serio);
        return retval;
 }
 
-ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
-                               ssize_t (*handler)(struct psmouse *, const char *, size_t))
+ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
+                               const char *buf, size_t count)
 {
        struct serio *serio = to_serio_port(dev);
-       struct psmouse *psmouse = serio_get_drvdata(serio);
-       struct psmouse *parent = NULL;
+       struct psmouse_attribute *attr = to_psmouse_attr(devattr);
+       struct psmouse *psmouse, *parent = NULL;
        int retval;
 
        retval = serio_pin_driver(serio);
@@ -1070,6 +1101,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
        if (retval)
                goto out_unpin;
 
+       psmouse = serio_get_drvdata(serio);
+
        if (psmouse->state == PSMOUSE_IGNORE) {
                retval = -ENODEV;
                goto out_up;
@@ -1082,7 +1115,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
 
        psmouse_deactivate(psmouse);
 
-       retval = handler(psmouse, buf, count);
+       retval = attr->set(psmouse, attr->data, buf, count);
 
        if (retval != -ENODEV)
                psmouse_activate(psmouse);
@@ -1097,12 +1130,34 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
        return retval;
 }
 
-static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
+static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf)
+{
+       unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+
+       return sprintf(buf, "%lu\n", *field);
+}
+
+static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
+{
+       unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset);
+       unsigned long value;
+       char *rest;
+
+       value = simple_strtoul(buf, &rest, 10);
+       if (*rest)
+               return -EINVAL;
+
+       *field = value;
+
+       return count;
+}
+
+static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, void *data, char *buf)
 {
        return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
 }
 
-static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        struct serio *serio = psmouse->ps2dev.serio;
        struct psmouse *parent = NULL;
@@ -1166,12 +1221,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *bu
        return count;
 }
 
-static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
-{
-       return sprintf(buf, "%d\n", psmouse->rate);
-}
-
-static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        unsigned long value;
        char *rest;
@@ -1184,12 +1234,7 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, const char *buf, s
        return count;
 }
 
-static ssize_t psmouse_attr_show_resolution(struct psmouse *psmouse, char *buf)
-{
-       return sprintf(buf, "%d\n", psmouse->resolution);
-}
-
-static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *buf, size_t count)
+static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
        unsigned long value;
        char *rest;
@@ -1202,23 +1247,6 @@ static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, const char *
        return count;
 }
 
-static ssize_t psmouse_attr_show_resetafter(struct psmouse *psmouse, char *buf)
-{
-       return sprintf(buf, "%d\n", psmouse->resetafter);
-}
-
-static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *buf, size_t count)
-{
-       unsigned long value;
-       char *rest;
-
-       value = simple_strtoul(buf, &rest, 10);
-       if (*rest)
-               return -EINVAL;
-
-       psmouse->resetafter = value;
-       return count;
-}
 
 static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
 {
@@ -1234,7 +1262,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
 
        *((unsigned int *)kp->arg) = proto->type;
 
-       return 0;                                       \
+       return 0;
 }
 
 static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
index 86691cf43433f182e9c2d7ac0d3f925dab5bb5bb..45d2bd774f00f02cf5644306760b8c29425d364d 100644 (file)
@@ -78,6 +78,7 @@ enum psmouse_type {
        PSMOUSE_SYNAPTICS,
        PSMOUSE_ALPS,
        PSMOUSE_LIFEBOOK,
+       PSMOUSE_TRACKPOINT,
        PSMOUSE_AUTO            /* This one should always be last */
 };
 
@@ -85,24 +86,37 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
 int psmouse_reset(struct psmouse *psmouse);
 void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
 
-ssize_t psmouse_attr_show_helper(struct device *dev, char *buf,
-                       ssize_t (*handler)(struct psmouse *, char *));
-ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t count,
-                       ssize_t (*handler)(struct psmouse *, const char *, size_t));
-
-#define PSMOUSE_DEFINE_ATTR(_name)                                             \
-static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *);            \
-static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
-static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b)               \
-{                                                                              \
-       return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name);       \
-}                                                                              \
-static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\
-{                                                                              \
-       return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name);      \
-}                                                                              \
-static struct device_attribute psmouse_attr_##_name =                          \
-       __ATTR(_name, S_IWUSR | S_IRUGO,                                        \
-               psmouse_do_show_##_name, psmouse_do_set_##_name);
+
+struct psmouse_attribute {
+       struct device_attribute dattr;
+       void *data;
+       ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf);
+       ssize_t (*set)(struct psmouse *psmouse, void *data,
+                       const char *buf, size_t count);
+};
+#define to_psmouse_attr(a)     container_of((a), struct psmouse_attribute, dattr)
+
+ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *attr,
+                                char *buf);
+ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t count);
+
+#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set)                  \
+static ssize_t _show(struct psmouse *, void *data, char *);                    \
+static ssize_t _set(struct psmouse *, void *data, const char *, size_t);       \
+static struct psmouse_attribute psmouse_attr_##_name = {                       \
+       .dattr  = {                                                             \
+               .attr   = {                                                     \
+                       .name   = __stringify(_name),                           \
+                       .mode   = _mode,                                        \
+                       .owner  = THIS_MODULE,                                  \
+               },                                                              \
+               .show   = psmouse_attr_show_helper,                             \
+               .store  = psmouse_attr_set_helper,                              \
+       },                                                                      \
+       .data   = _data,                                                        \
+       .show   = _show,                                                        \
+       .set    = _set,                                                         \
+}
 
 #endif /* _PSMOUSE_H */
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
new file mode 100644 (file)
index 0000000..b4898d8
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Stephen Evanchik <evanchsa@gmail.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.
+ *
+ * Trademarks are the property of their respective owners.
+ */
+
+#include <linux/delay.h>
+#include <linux/serio.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/libps2.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "psmouse.h"
+#include "trackpoint.h"
+
+/*
+ * Device IO: read, write and toggle bit
+ */
+static int trackpoint_read(struct ps2dev *ps2dev, unsigned char loc, unsigned char *results)
+{
+       if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+           ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int trackpoint_write(struct ps2dev *ps2dev, unsigned char loc, unsigned char val)
+{
+       if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+           ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) ||
+           ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
+           ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, val))) {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int trackpoint_toggle_bit(struct ps2dev *ps2dev, unsigned char loc, unsigned char mask)
+{
+       /* Bad things will happen if the loc param isn't in this range */
+       if (loc < 0x20 || loc >= 0x2F)
+               return -1;
+
+       if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) ||
+           ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_TOGGLE)) ||
+           ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, loc)) ||
+           ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, mask))) {
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/*
+ * Trackpoint-specific attributes
+ */
+struct trackpoint_attr_data {
+       size_t field_offset;
+       unsigned char command;
+       unsigned char mask;
+};
+
+static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf)
+{
+       struct trackpoint_data *tp = psmouse->private;
+       struct trackpoint_attr_data *attr = data;
+       unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+
+       return sprintf(buf, "%u\n", *field);
+}
+
+static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
+                                       const char *buf, size_t count)
+{
+       struct trackpoint_data *tp = psmouse->private;
+       struct trackpoint_attr_data *attr = data;
+       unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+       unsigned long value;
+       char *rest;
+
+       value = simple_strtoul(buf, &rest, 10);
+       if (*rest || value > 255)
+               return -EINVAL;
+
+       *field = value;
+       trackpoint_write(&psmouse->ps2dev, attr->command, value);
+
+       return count;
+}
+
+#define TRACKPOINT_INT_ATTR(_name, _command)                                   \
+       static struct trackpoint_attr_data trackpoint_attr_##_name = {          \
+               .field_offset = offsetof(struct trackpoint_data, _name),        \
+               .command = _command,                                            \
+       };                                                                      \
+       PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO,                           \
+                           &trackpoint_attr_##_name,                           \
+                           trackpoint_show_int_attr, trackpoint_set_int_attr)
+
+static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
+                                       const char *buf, size_t count)
+{
+       struct trackpoint_data *tp = psmouse->private;
+       struct trackpoint_attr_data *attr = data;
+       unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
+       unsigned long value;
+       char *rest;
+
+       value = simple_strtoul(buf, &rest, 10);
+       if (*rest || value > 1)
+               return -EINVAL;
+
+       if (*field != value) {
+               *field = value;
+               trackpoint_toggle_bit(&psmouse->ps2dev, attr->command, attr->mask);
+       }
+
+       return count;
+}
+
+
+#define TRACKPOINT_BIT_ATTR(_name, _command, _mask)                            \
+       static struct trackpoint_attr_data trackpoint_attr_##_name = {          \
+               .field_offset   = offsetof(struct trackpoint_data, _name),      \
+               .command        = _command,                                     \
+               .mask           = _mask,                                        \
+       };                                                                      \
+       PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO,                           \
+                           &trackpoint_attr_##_name,                           \
+                           trackpoint_show_int_attr, trackpoint_set_bit_attr)
+
+TRACKPOINT_INT_ATTR(sensitivity, TP_SENS);
+TRACKPOINT_INT_ATTR(speed, TP_SPEED);
+TRACKPOINT_INT_ATTR(inertia, TP_INERTIA);
+TRACKPOINT_INT_ATTR(reach, TP_REACH);
+TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS);
+TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG);
+TRACKPOINT_INT_ATTR(thresh, TP_THRESH);
+TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH);
+TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME);
+TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV);
+
+TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+static struct attribute *trackpoint_attrs[] = {
+       &psmouse_attr_sensitivity.dattr.attr,
+       &psmouse_attr_speed.dattr.attr,
+       &psmouse_attr_inertia.dattr.attr,
+       &psmouse_attr_reach.dattr.attr,
+       &psmouse_attr_draghys.dattr.attr,
+       &psmouse_attr_mindrag.dattr.attr,
+       &psmouse_attr_thresh.dattr.attr,
+       &psmouse_attr_upthresh.dattr.attr,
+       &psmouse_attr_ztime.dattr.attr,
+       &psmouse_attr_jenks.dattr.attr,
+       &psmouse_attr_press_to_select.dattr.attr,
+       &psmouse_attr_skipback.dattr.attr,
+       &psmouse_attr_ext_dev.dattr.attr,
+       NULL
+};
+
+static struct attribute_group trackpoint_attr_group = {
+       .attrs = trackpoint_attrs,
+};
+
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+       sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+       kfree(psmouse->private);
+       psmouse->private = NULL;
+}
+
+static int trackpoint_sync(struct psmouse *psmouse)
+{
+       unsigned char toggle;
+       struct trackpoint_data *tp = psmouse->private;
+
+       if (!tp)
+               return -1;
+
+       /* Disable features that may make device unusable with this driver */
+       trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
+       if (toggle & TP_MASK_TWOHAND)
+               trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, TP_MASK_TWOHAND);
+
+       trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, &toggle);
+       if (toggle & TP_MASK_SOURCE_TAG)
+               trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, TP_MASK_SOURCE_TAG);
+
+       trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_MB, &toggle);
+       if (toggle & TP_MASK_MB)
+               trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_MB, TP_MASK_MB);
+
+       /* Push the config to the device */
+       trackpoint_write(&psmouse->ps2dev, TP_SENS, tp->sensitivity);
+       trackpoint_write(&psmouse->ps2dev, TP_INERTIA, tp->inertia);
+       trackpoint_write(&psmouse->ps2dev, TP_SPEED, tp->speed);
+
+       trackpoint_write(&psmouse->ps2dev, TP_REACH, tp->reach);
+       trackpoint_write(&psmouse->ps2dev, TP_DRAGHYS, tp->draghys);
+       trackpoint_write(&psmouse->ps2dev, TP_MINDRAG, tp->mindrag);
+
+       trackpoint_write(&psmouse->ps2dev, TP_THRESH, tp->thresh);
+       trackpoint_write(&psmouse->ps2dev, TP_UP_THRESH, tp->upthresh);
+
+       trackpoint_write(&psmouse->ps2dev, TP_Z_TIME, tp->ztime);
+       trackpoint_write(&psmouse->ps2dev, TP_JENKS_CURV, tp->jenks);
+
+       trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_PTSON, &toggle);
+       if (((toggle & TP_MASK_PTSON) == TP_MASK_PTSON) != tp->press_to_select)
+                trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_PTSON, TP_MASK_PTSON);
+
+       trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, &toggle);
+       if (((toggle & TP_MASK_SKIPBACK) == TP_MASK_SKIPBACK) != tp->skipback)
+               trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK);
+
+       trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, &toggle);
+       if (((toggle & TP_MASK_EXT_DEV) == TP_MASK_EXT_DEV) != tp->ext_dev)
+               trackpoint_toggle_bit(&psmouse->ps2dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV);
+
+       return 0;
+}
+
+static void trackpoint_defaults(struct trackpoint_data *tp)
+{
+       tp->press_to_select = TP_DEF_PTSON;
+       tp->sensitivity = TP_DEF_SENS;
+       tp->speed = TP_DEF_SPEED;
+       tp->reach = TP_DEF_REACH;
+
+       tp->draghys = TP_DEF_DRAGHYS;
+       tp->mindrag = TP_DEF_MINDRAG;
+
+       tp->thresh = TP_DEF_THRESH;
+       tp->upthresh = TP_DEF_UP_THRESH;
+
+       tp->ztime = TP_DEF_Z_TIME;
+       tp->jenks = TP_DEF_JENKS_CURV;
+
+       tp->inertia = TP_DEF_INERTIA;
+       tp->skipback = TP_DEF_SKIPBACK;
+       tp->ext_dev = TP_DEF_EXT_DEV;
+}
+
+int trackpoint_detect(struct psmouse *psmouse, int set_properties)
+{
+       struct trackpoint_data *priv;
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       unsigned char firmware_id;
+       unsigned char button_info;
+       unsigned char param[2];
+
+       param[0] = param[1] = 0;
+
+       if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+               return -1;
+
+       if (param[0] != TP_MAGIC_IDENT)
+               return -1;
+
+       if (!set_properties)
+               return 0;
+
+       firmware_id = param[1];
+
+       if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
+               printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
+               button_info = 0;
+       }
+
+       psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL);
+       if (!priv)
+               return -1;
+
+       psmouse->vendor = "IBM";
+       psmouse->name = "TrackPoint";
+
+       psmouse->reconnect = trackpoint_sync;
+       psmouse->disconnect = trackpoint_disconnect;
+
+       trackpoint_defaults(priv);
+       trackpoint_sync(psmouse);
+
+       sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
+
+       printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
+               firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
+
+       return 0;
+}
+
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
new file mode 100644 (file)
index 0000000..9857d8b
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * IBM TrackPoint PS/2 mouse driver
+ *
+ * Stephen Evanchik <evanchsa@gmail.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.
+ */
+
+#ifndef _TRACKPOINT_H
+#define _TRACKPOINT_H
+
+/*
+ * These constants are from the TrackPoint System
+ * Engineering documentation Version 4 from IBM Watson
+ * research:
+ *     http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
+ */
+
+#define TP_COMMAND             0xE2    /* Commands start with this */
+
+#define TP_READ_ID             0xE1    /* Sent for device identification */
+#define TP_MAGIC_IDENT         0x01    /* Sent after a TP_READ_ID followed */
+                                       /* by the firmware ID */
+
+
+/*
+ * Commands
+ */
+#define TP_RECALIB             0x51    /* Recalibrate */
+#define TP_POWER_DOWN          0x44    /* Can only be undone through HW reset */
+#define TP_EXT_DEV             0x21    /* Determines if external device is connected (RO) */
+#define TP_EXT_BTN             0x4B    /* Read extended button status */
+#define TP_POR                 0x7F    /* Execute Power on Reset */
+#define TP_POR_RESULTS         0x25    /* Read Power on Self test results */
+#define TP_DISABLE_EXT         0x40    /* Disable external pointing device */
+#define TP_ENABLE_EXT          0x41    /* Enable external pointing device */
+
+/*
+ * Mode manipulation
+ */
+#define TP_SET_SOFT_TRANS      0x4E    /* Set mode */
+#define TP_CANCEL_SOFT_TRANS   0xB9    /* Cancel mode */
+#define TP_SET_HARD_TRANS      0x45    /* Mode can only be set */
+
+
+/*
+ * Register oriented commands/properties
+ */
+#define TP_WRITE_MEM           0x81
+#define TP_READ_MEM            0x80    /* Not used in this implementation */
+
+/*
+* RAM Locations for properties
+ */
+#define TP_SENS                        0x4A    /* Sensitivity */
+#define TP_MB                  0x4C    /* Read Middle Button Status (RO) */
+#define TP_INERTIA             0x4D    /* Negative Inertia */
+#define TP_SPEED               0x60    /* Speed of TP Cursor */
+#define TP_REACH               0x57    /* Backup for Z-axis press */
+#define TP_DRAGHYS             0x58    /* Drag Hysteresis */
+                                       /* (how hard it is to drag */
+                                       /* with Z-axis pressed) */
+
+#define TP_MINDRAG             0x59    /* Minimum amount of force needed */
+                                       /* to trigger dragging */
+
+#define TP_THRESH              0x5C    /* Minimum value for a Z-axis press */
+#define TP_UP_THRESH           0x5A    /* Used to generate a 'click' on Z-axis */
+#define TP_Z_TIME              0x5E    /* How sharp of a press */
+#define TP_JENKS_CURV          0x5D    /* Minimum curvature for double click */
+
+/*
+ * Toggling Flag bits
+ */
+#define TP_TOGGLE              0x47    /* Toggle command */
+
+#define TP_TOGGLE_MB           0x23    /* Disable/Enable Middle Button */
+#define TP_MASK_MB                     0x01
+#define TP_TOGGLE_EXT_DEV      0x23    /* Toggle external device */
+#define TP_MASK_EXT_DEV                        0x02
+#define TP_TOGGLE_DRIFT                0x23    /* Drift Correction */
+#define TP_MASK_DRIFT                  0x80
+#define TP_TOGGLE_BURST                0x28    /* Burst Mode */
+#define TP_MASK_BURST                  0x80
+#define TP_TOGGLE_PTSON                0x2C    /* Press to Select */
+#define TP_MASK_PTSON                  0x01
+#define TP_TOGGLE_HARD_TRANS   0x2C    /* Alternate method to set Hard Transparency */
+#define TP_MASK_HARD_TRANS             0x80
+#define TP_TOGGLE_TWOHAND      0x2D    /* Two handed */
+#define TP_MASK_TWOHAND                        0x01
+#define TP_TOGGLE_STICKY_TWO   0x2D    /* Sticky two handed */
+#define TP_MASK_STICKY_TWO             0x04
+#define TP_TOGGLE_SKIPBACK     0x2D    /* Suppress movement after drag release */
+#define TP_MASK_SKIPBACK               0x08
+#define TP_TOGGLE_SOURCE_TAG   0x20    /* Bit 3 of the first packet will be set to
+                                          to the origin of the packet (external or TP) */
+#define TP_MASK_SOURCE_TAG             0x80
+#define TP_TOGGLE_EXT_TAG      0x22    /* Bit 3 of the first packet coming from the
+                                          external device will be forced to 1 */
+#define TP_MASK_EXT_TAG                        0x04
+
+
+/* Power on Self Test Results */
+#define TP_POR_SUCCESS         0x3B
+
+/*
+ * Default power on values
+ */
+#define TP_DEF_SENS            0x80
+#define TP_DEF_INERTIA         0x06
+#define TP_DEF_SPEED           0x61
+#define TP_DEF_REACH           0x0A
+
+#define TP_DEF_DRAGHYS         0xFF
+#define TP_DEF_MINDRAG         0x14
+
+#define TP_DEF_THRESH          0x08
+#define TP_DEF_UP_THRESH       0xFF
+#define TP_DEF_Z_TIME          0x26
+#define TP_DEF_JENKS_CURV      0x87
+
+/* Toggles */
+#define TP_DEF_MB              0x00
+#define TP_DEF_PTSON           0x00
+#define TP_DEF_SKIPBACK                0x00
+#define TP_DEF_EXT_DEV         0x01
+
+#define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd))
+
+struct trackpoint_data
+{
+       unsigned char sensitivity, speed, inertia, reach;
+       unsigned char draghys, mindrag;
+       unsigned char thresh, upthresh;
+       unsigned char ztime, jenks;
+
+       unsigned char press_to_select;
+       unsigned char skipback;
+
+       unsigned char ext_dev;
+};
+
+extern int trackpoint_detect(struct psmouse *psmouse, int set_properties);
+
+#endif /* _TRACKPOINT_H */
index c9e633d21d9035b4a91b1da30a04f1ae8d010890..9a92216442501d066ec4b41476ad37b41ffbfd03 100644 (file)
@@ -69,16 +69,16 @@ static inline int i8042_platform_init(void)
  */
 #if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
        if (!request_region(I8042_DATA_REG, 16, "i8042"))
-               return -1;
+               return -EBUSY;
 #endif
 
         i8042_reset = 1;
 
 #if defined(CONFIG_PPC64)
        if (check_legacy_ioport(I8042_DATA_REG))
-               return -1;
+               return -EBUSY;
        if (!request_region(I8042_DATA_REG, 16, "i8042"))
-               return -1;
+               return -EBUSY;
 #endif
        return 0;
 }
index 863b9c95fbb86964713ff52d075f6f3d7ede377e..ee1ad27d6ed06ef70370f3096352b37acb1c1368 100644 (file)
@@ -58,7 +58,7 @@ static inline int i8042_platform_init(void)
 #if 0
        /* XXX sgi_kh is a virtual address */
        if (!request_mem_region(sgi_kh, sizeof(struct hpc_keyb), "i8042"))
-               return 1;
+               return -EBUSY;
 #endif
 
        i8042_reset = 1;
index 5c20ab131488e038228f642e5c7e0705834257e9..13fd7108eb2836ad5eb7625fab88c1d2dbf425de 100644 (file)
@@ -53,7 +53,7 @@ static inline int i8042_platform_init(void)
 #if 0
        /* XXX JAZZ_KEYBOARD_ADDRESS is a virtual address */
        if (!request_mem_region(JAZZ_KEYBOARD_ADDRESS, 2, "i8042"))
-               return 1;
+               return -EBUSY;
 #endif
 
        return 0;
index da2a19812485208e72d4a5c55c60c3f0f2ed90af..ed9446f6d7e3332cdf8f9ec4f6ec0f4b1fb6784c 100644 (file)
@@ -48,10 +48,10 @@ static inline void i8042_write_command(int val)
 #define OBP_PS2MS_NAME1                "kdmouse"
 #define OBP_PS2MS_NAME2                "mouse"
 
-static int i8042_platform_init(void)
+static int __init i8042_platform_init(void)
 {
 #ifndef CONFIG_PCI
-       return -1;
+       return -ENODEV;
 #else
        char prop[128];
        int len;
@@ -59,14 +59,14 @@ static int i8042_platform_init(void)
        len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
        if (len < 0) {
                printk("i8042: Cannot get name property of root OBP node.\n");
-               return -1;
+               return -ENODEV;
        }
        if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
                /* Hardcoded values for MrCoffee.  */
                i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
                kbd_iobase = ioremap(0x71300060, 8);
                if (!kbd_iobase)
-                       return -1;
+                       return -ENODEV;
        } else {
                struct linux_ebus *ebus;
                struct linux_ebus_device *edev;
@@ -78,7 +78,7 @@ static int i8042_platform_init(void)
                                        goto edev_found;
                        }
                }
-               return -1;
+               return -ENODEV;
 
        edev_found:
                for_each_edevchild(edev, child) {
@@ -96,7 +96,7 @@ static int i8042_platform_init(void)
                    i8042_aux_irq == -1) {
                        printk("i8042: Error, 8042 device lacks both kbd and "
                               "mouse nodes.\n");
-                       return -1;
+                       return -ENODEV;
                }
        }
 
index 03877c84e6ff97487b6585a5efa8c953619cd39d..273bb3b08cfa254146cf1b6362bfc8b1df1e224e 100644 (file)
@@ -137,6 +137,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),
                },
        },
+       {
+               .ident = "Fujitsu-Siemens Lifebook E4010",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
+               },
+       },
        {
                .ident = "Toshiba P10",
                .matches = {
@@ -256,9 +263,10 @@ static void i8042_pnp_exit(void)
        }
 }
 
-static int i8042_pnp_init(void)
+static int __init i8042_pnp_init(void)
 {
-       int result_kbd, result_aux;
+       int result_kbd = 0, result_aux = 0;
+       char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
 
        if (i8042_nopnp) {
                printk(KERN_INFO "i8042: PNP detection disabled\n");
@@ -267,6 +275,7 @@ static int i8042_pnp_init(void)
 
        if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
                i8042_pnp_kbd_registered = 1;
+
        if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
                i8042_pnp_aux_registered = 1;
 
@@ -280,6 +289,27 @@ static int i8042_pnp_init(void)
 #endif
        }
 
+       if (result_kbd > 0)
+               snprintf(kbd_irq_str, sizeof(kbd_irq_str),
+                       "%d", i8042_pnp_kbd_irq);
+       if (result_aux > 0)
+               snprintf(aux_irq_str, sizeof(aux_irq_str),
+                       "%d", i8042_pnp_aux_irq);
+
+       printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n",
+               i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "",
+               i8042_pnp_aux_name,
+               i8042_pnp_data_reg, i8042_pnp_command_reg,
+               kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "",
+               aux_irq_str);
+
+#if defined(__ia64__)
+       if (result_kbd <= 0)
+               i8042_nokbd = 1;
+       if (result_aux <= 0)
+               i8042_noaux = 1;
+#endif
+
        if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
              i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
                printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
@@ -294,53 +324,47 @@ static int i8042_pnp_init(void)
                i8042_pnp_command_reg = i8042_command_reg;
        }
 
-       if (!i8042_pnp_kbd_irq) {
-               printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
+       if (!i8042_nokbd && !i8042_pnp_kbd_irq) {
+               printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq);
                i8042_pnp_kbd_irq = i8042_kbd_irq;
        }
 
-       if (!i8042_pnp_aux_irq) {
-               printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
+       if (!i8042_noaux && !i8042_pnp_aux_irq) {
+               printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq);
                i8042_pnp_aux_irq = i8042_aux_irq;
        }
 
-#if defined(__ia64__)
-       if (result_aux <= 0)
-               i8042_noaux = 1;
-#endif
-
        i8042_data_reg = i8042_pnp_data_reg;
        i8042_command_reg = i8042_pnp_command_reg;
        i8042_kbd_irq = i8042_pnp_kbd_irq;
        i8042_aux_irq = i8042_pnp_aux_irq;
 
-       printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
-               i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
-               i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
-               (result_aux > 0) ? "," : "", i8042_aux_irq);
-
        return 0;
 }
 
+#else
+static inline int i8042_pnp_init(void) { return 0; }
+static inline void i8042_pnp_exit(void) { }
 #endif
 
-static inline int i8042_platform_init(void)
+static int __init i8042_platform_init(void)
 {
+       int retval;
+
 /*
  * On ix86 platforms touching the i8042 data register region can do really
  * bad things. Because of this the region is always reserved on ix86 boxes.
  *
  *     if (!request_region(I8042_DATA_REG, 16, "i8042"))
- *             return -1;
+ *             return -EBUSY;
  */
 
        i8042_kbd_irq = I8042_MAP_IRQ(1);
        i8042_aux_irq = I8042_MAP_IRQ(12);
 
-#ifdef CONFIG_PNP
-       if (i8042_pnp_init())
-               return -1;
-#endif
+       retval = i8042_pnp_init();
+       if (retval)
+               return retval;
 
 #if defined(__ia64__)
         i8042_reset = 1;
@@ -354,14 +378,12 @@ static inline int i8042_platform_init(void)
                i8042_nomux = 1;
 #endif
 
-       return 0;
+       return retval;
 }
 
 static inline void i8042_platform_exit(void)
 {
-#ifdef CONFIG_PNP
        i8042_pnp_exit();
-#endif
 }
 
 #endif /* _I8042_X86IA64IO_H */
index 708a1d3beab975100bd6dbf4f88754c9d99e3f2a..40d451ce07ffecac8052e973e126ae112e256505 100644 (file)
@@ -27,6 +27,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");
 MODULE_LICENSE("GPL");
 
+static unsigned int i8042_nokbd;
+module_param_named(nokbd, i8042_nokbd, bool, 0);
+MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port.");
+
 static unsigned int i8042_noaux;
 module_param_named(noaux, i8042_noaux, bool, 0);
 MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");
@@ -338,10 +342,10 @@ static int i8042_open(struct serio *serio)
 
        return 0;
 
-activate_fail:
+ activate_fail:
        free_irq(port->irq, i8042_request_irq_cookie);
 
-irq_fail:
+ irq_fail:
        serio_unregister_port_delayed(serio);
 
        return -1;
@@ -485,7 +489,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                serio_interrupt(port->serio, data, dfl, regs);
 
        ret = 1;
-out:
+ out:
        return IRQ_RETVAL(ret);
 }
 
@@ -552,7 +556,7 @@ static int i8042_enable_mux_ports(void)
  * Enable all muxed ports.
  */
 
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
                i8042_command(&param, I8042_CMD_MUX_PFX + i);
                i8042_command(&param, I8042_CMD_AUX_ENABLE);
        }
@@ -682,7 +686,7 @@ static int __init i8042_port_register(struct i8042_port *port)
                kfree(port->serio);
                port->serio = NULL;
                i8042_ctr |= port->disable;
-               return -1;
+               return -EIO;
        }
 
        printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
@@ -977,85 +981,88 @@ static struct device_driver i8042_driver = {
        .shutdown       = i8042_shutdown,
 };
 
-static void __init i8042_create_kbd_port(void)
+static int __init i8042_create_kbd_port(void)
 {
        struct serio *serio;
        struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
 
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
-       if (serio) {
-               memset(serio, 0, sizeof(struct serio));
-               serio->id.type          = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
-               serio->write            = i8042_dumbkbd ? NULL : i8042_kbd_write;
-               serio->open             = i8042_open;
-               serio->close            = i8042_close;
-               serio->start            = i8042_start;
-               serio->stop             = i8042_stop;
-               serio->port_data        = port;
-               serio->dev.parent       = &i8042_platform_device->dev;
-               strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
-               strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
-
-               port->serio = serio;
-               i8042_port_register(port);
-       }
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       serio->id.type          = i8042_direct ? SERIO_8042 : SERIO_8042_XL;
+       serio->write            = i8042_dumbkbd ? NULL : i8042_kbd_write;
+       serio->open             = i8042_open;
+       serio->close            = i8042_close;
+       serio->start            = i8042_start;
+       serio->stop             = i8042_stop;
+       serio->port_data        = port;
+       serio->dev.parent       = &i8042_platform_device->dev;
+       strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
+       strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+
+       port->serio = serio;
+
+       return i8042_port_register(port);
 }
 
-static void __init i8042_create_aux_port(void)
+static int __init i8042_create_aux_port(void)
 {
        struct serio *serio;
        struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
 
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
-       if (serio) {
-               memset(serio, 0, sizeof(struct serio));
-               serio->id.type          = SERIO_8042;
-               serio->write            = i8042_aux_write;
-               serio->open             = i8042_open;
-               serio->close            = i8042_close;
-               serio->start            = i8042_start;
-               serio->stop             = i8042_stop;
-               serio->port_data        = port;
-               serio->dev.parent       = &i8042_platform_device->dev;
-               strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
-               strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
-
-               port->serio = serio;
-               i8042_port_register(port);
-       }
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       serio->id.type          = SERIO_8042;
+       serio->write            = i8042_aux_write;
+       serio->open             = i8042_open;
+       serio->close            = i8042_close;
+       serio->start            = i8042_start;
+       serio->stop             = i8042_stop;
+       serio->port_data        = port;
+       serio->dev.parent       = &i8042_platform_device->dev;
+       strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
+       strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+
+       port->serio = serio;
+
+       return i8042_port_register(port);
 }
 
-static void __init i8042_create_mux_port(int index)
+static int __init i8042_create_mux_port(int index)
 {
        struct serio *serio;
        struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
 
-       serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
-       if (serio) {
-               memset(serio, 0, sizeof(struct serio));
-               serio->id.type          = SERIO_8042;
-               serio->write            = i8042_aux_write;
-               serio->open             = i8042_open;
-               serio->close            = i8042_close;
-               serio->start            = i8042_start;
-               serio->stop             = i8042_stop;
-               serio->port_data        = port;
-               serio->dev.parent       = &i8042_platform_device->dev;
-               snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
-               snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
-
-               *port = i8042_ports[I8042_AUX_PORT_NO];
-               port->exists = 0;
-               snprintf(port->name, sizeof(port->name), "AUX%d", index);
-               port->mux = index;
-               port->serio = serio;
-               i8042_port_register(port);
-       }
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       serio->id.type          = SERIO_8042;
+       serio->write            = i8042_aux_write;
+       serio->open             = i8042_open;
+       serio->close            = i8042_close;
+       serio->start            = i8042_start;
+       serio->stop             = i8042_stop;
+       serio->port_data        = port;
+       serio->dev.parent       = &i8042_platform_device->dev;
+       snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
+       snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
+
+       *port = i8042_ports[I8042_AUX_PORT_NO];
+       port->exists = 0;
+       snprintf(port->name, sizeof(port->name), "AUX%d", index);
+       port->mux = index;
+       port->serio = serio;
+
+       return i8042_port_register(port);
 }
 
 static int __init i8042_init(void)
 {
-       int i;
+       int i, have_ports = 0;
        int err;
 
        dbg_init();
@@ -1063,43 +1070,73 @@ static int __init i8042_init(void)
        init_timer(&i8042_timer);
        i8042_timer.function = i8042_timer_func;
 
-       if (i8042_platform_init())
-               return -EBUSY;
+       err = i8042_platform_init();
+       if (err)
+               return err;
 
        i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
        i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
 
        if (i8042_controller_init()) {
-               i8042_platform_exit();
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_platform_exit;
        }
 
        err = driver_register(&i8042_driver);
-       if (err) {
-               i8042_platform_exit();
-               return err;
-       }
+       if (err)
+               goto err_controller_cleanup;
 
        i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
        if (IS_ERR(i8042_platform_device)) {
-               driver_unregister(&i8042_driver);
-               i8042_platform_exit();
-               return PTR_ERR(i8042_platform_device);
+               err = PTR_ERR(i8042_platform_device);
+               goto err_unregister_driver;
        }
 
        if (!i8042_noaux && !i8042_check_aux()) {
-               if (!i8042_nomux && !i8042_check_mux())
-                       for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
-                               i8042_create_mux_port(i);
-               else
-                       i8042_create_aux_port();
+               if (!i8042_nomux && !i8042_check_mux()) {
+                       for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
+                               err = i8042_create_mux_port(i);
+                               if (err)
+                                       goto err_unregister_ports;
+                       }
+               } else {
+                       err = i8042_create_aux_port();
+                       if (err)
+                               goto err_unregister_ports;
+               }
+               have_ports = 1;
        }
 
-       i8042_create_kbd_port();
+       if (!i8042_nokbd) {
+               err = i8042_create_kbd_port();
+               if (err)
+                       goto err_unregister_ports;
+               have_ports = 1;
+       }
+
+       if (!have_ports) {
+               err = -ENODEV;
+               goto err_unregister_device;
+       }
 
        mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
        return 0;
+
+ err_unregister_ports:
+       for (i = 0; i < I8042_NUM_PORTS; i++)
+               if (i8042_ports[i].serio)
+                       serio_unregister_port(i8042_ports[i].serio);
+ err_unregister_device:
+       platform_device_unregister(i8042_platform_device);
+ err_unregister_driver:
+       driver_unregister(&i8042_driver);
+ err_controller_cleanup:
+       i8042_controller_cleanup();
+ err_platform_exit:
+       i8042_platform_exit();
+
+       return err;
 }
 
 static void __exit i8042_exit(void)
index baf4bcad9bf93a825c34941ea57e9f244b1d5bff..0afe442db3b0011568fc96f5f5c2d2baae591342 100644 (file)
@@ -283,23 +283,19 @@ static void bsd_free (void *state)
                /*
                 * Release the dictionary
                 */
-               if (db->dict) {
-                       vfree (db->dict);
-                       db->dict = NULL;
-               }
+               vfree(db->dict);
+               db->dict = NULL;
 
                /*
                 * Release the string buffer
                 */
-               if (db->lens) {
-                       vfree (db->lens);
-                       db->lens = NULL;
-               }
+               vfree(db->lens);
+               db->lens = NULL;
 
                /*
                 * Finally release the structure itself.
                 */
-               kfree (db);
+               kfree(db);
        }
 }
 
index eebcb0b97f0e9b6f05d0df1bfa12633285dd9f37..8a7d54a5c97d6634525d31e536aa3af098087a5a 100644 (file)
@@ -1953,7 +1953,8 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
                kfree(d->rcvcount);
        if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
                printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
-               if (!adding) kfree(d->rcverr);
+               if (!adding)
+                       kfree(d->rcverr);
                return -1;
        }
        memset((char *) d->rcvcount, 0, sizeof(int) * m);
index 41df4cda66e2f27b668a98988aaf80121fb16236..2fba2bbe72d8f627136d5983b40c421c55220f6d 100644 (file)
@@ -270,19 +270,20 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
 
        if (!page)
                return ERR_PTR(-ENOMEM);
-       do {
-               ITERATE_RDEV(mddev, rdev, tmp)
-                       if (rdev->in_sync && !rdev->faulty)
-                               goto found;
-               return ERR_PTR(-EIO);
 
-       found:
+       ITERATE_RDEV(mddev, rdev, tmp) {
+               if (! rdev->in_sync || rdev->faulty)
+                       continue;
+
                target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
 
-       } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+               if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
+                       page->index = index;
+                       return page;
+               }
+       }
+       return ERR_PTR(-EIO);
 
-       page->index = index;
-       return page;
 }
 
 static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
@@ -437,6 +438,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
        printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
        printk(KERN_DEBUG "     sync size: %llu KB\n",
                        (unsigned long long)le64_to_cpu(sb->sync_size)/2);
+       printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
        kunmap(bitmap->sb_page);
 }
 
@@ -445,7 +447,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 {
        char *reason = NULL;
        bitmap_super_t *sb;
-       unsigned long chunksize, daemon_sleep;
+       unsigned long chunksize, daemon_sleep, write_behind;
        unsigned long bytes_read;
        unsigned long long events;
        int err = -EINVAL;
@@ -474,6 +476,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 
        chunksize = le32_to_cpu(sb->chunksize);
        daemon_sleep = le32_to_cpu(sb->daemon_sleep);
+       write_behind = le32_to_cpu(sb->write_behind);
 
        /* verify that the bitmap-specific fields are valid */
        if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -485,7 +488,9 @@ static int bitmap_read_sb(struct bitmap *bitmap)
        else if ((1 << ffz(~chunksize)) != chunksize)
                reason = "bitmap chunksize not a power of 2";
        else if (daemon_sleep < 1 || daemon_sleep > 15)
-               reason = "daemon sleep period out of range";
+               reason = "daemon sleep period out of range (1-15s)";
+       else if (write_behind > COUNTER_MAX)
+               reason = "write-behind limit out of range (0 - 16383)";
        if (reason) {
                printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
                        bmname(bitmap), reason);
@@ -518,8 +523,12 @@ success:
        /* assign fields using values from superblock */
        bitmap->chunksize = chunksize;
        bitmap->daemon_sleep = daemon_sleep;
+       bitmap->daemon_lastrun = jiffies;
+       bitmap->max_write_behind = write_behind;
        bitmap->flags |= sb->state;
        bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+       if (sb->state & BITMAP_STALE)
+               bitmap->events_cleared = bitmap->mddev->events;
        err = 0;
 out:
        kunmap(bitmap->sb_page);
@@ -617,7 +626,7 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
                page_cache_release(sb_page);
 }
 
-static void bitmap_stop_daemons(struct bitmap *bitmap);
+static void bitmap_stop_daemon(struct bitmap *bitmap);
 
 /* dequeue the next item in a page list -- don't call from irq context */
 static struct page_list *dequeue_page(struct bitmap *bitmap)
@@ -659,7 +668,7 @@ static void bitmap_file_put(struct bitmap *bitmap)
        bitmap->file = NULL;
        spin_unlock_irqrestore(&bitmap->lock, flags);
 
-       bitmap_stop_daemons(bitmap);
+       bitmap_stop_daemon(bitmap);
 
        drain_write_queues(bitmap);
 
@@ -818,7 +827,7 @@ int bitmap_unplug(struct bitmap *bitmap)
        return 0;
 }
 
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed);
 /* * bitmap_init_from_disk -- called at bitmap_create time to initialize
  * the in-memory bitmap from the on-disk bitmap -- also, sets up the
  * memory mapping of the bitmap file
@@ -826,8 +835,11 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset);
  *   if there's no bitmap file, or if the bitmap file had been
  *   previously kicked from the array, we mark all the bits as
  *   1's in order to cause a full resync.
+ *
+ * We ignore all bits for sectors that end earlier than 'start'.
+ * This is used when reading an out-of-date bitmap...
  */
-static int bitmap_init_from_disk(struct bitmap *bitmap)
+static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 {
        unsigned long i, chunks, index, oldindex, bit;
        struct page *page = NULL, *oldpage = NULL;
@@ -914,7 +926,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
                                 * whole page and write it out
                                 */
                                memset(page_address(page) + offset, 0xff,
-                                       PAGE_SIZE - offset);
+                                      PAGE_SIZE - offset);
                                ret = write_page(bitmap, page, 1);
                                if (ret) {
                                        kunmap(page);
@@ -928,8 +940,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap)
                }
                if (test_bit(bit, page_address(page))) {
                        /* if the disk bit is set, set the memory bit */
-                       bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap));
+                       bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
+                                              ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
+                               );
                        bit_cnt++;
+                       set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
                }
        }
 
@@ -1141,6 +1156,9 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
                err = -EINTR;
                goto out;
        }
+       if (bitmap == NULL)
+               /* about to be stopped. */
+               return;
 
        PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
        /* wait on bitmap page writebacks */
@@ -1170,21 +1188,12 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
        }
 }
 
-static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
                                void (*func)(mddev_t *), char *name)
 {
        mdk_thread_t *daemon;
-       unsigned long flags;
        char namebuf[32];
 
-       spin_lock_irqsave(&bitmap->lock, flags);
-       *ptr = NULL;
-
-       if (!bitmap->file) /* no need for daemon if there's no backing file */
-               goto out_unlock;
-
-       spin_unlock_irqrestore(&bitmap->lock, flags);
-
 #ifdef INJECT_FATAL_FAULT_2
        daemon = NULL;
 #else
@@ -1194,47 +1203,32 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
        if (!daemon) {
                printk(KERN_ERR "%s: failed to start bitmap daemon\n",
                        bmname(bitmap));
-               return -ECHILD;
+               return ERR_PTR(-ECHILD);
        }
 
-       spin_lock_irqsave(&bitmap->lock, flags);
-       *ptr = daemon;
-
        md_wakeup_thread(daemon); /* start it running */
 
        PRINTK("%s: %s daemon (pid %d) started...\n",
                bmname(bitmap), name, daemon->tsk->pid);
-out_unlock:
-       spin_unlock_irqrestore(&bitmap->lock, flags);
-       return 0;
-}
 
-static int bitmap_start_daemons(struct bitmap *bitmap)
-{
-       int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
-                                       bitmap_writeback_daemon, "bitmap_wb");
-       return err;
+       return daemon;
 }
 
-static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+static void bitmap_stop_daemon(struct bitmap *bitmap)
 {
-       mdk_thread_t *daemon;
-       unsigned long flags;
-
-       spin_lock_irqsave(&bitmap->lock, flags);
-       daemon = *ptr;
-       *ptr = NULL;
-       spin_unlock_irqrestore(&bitmap->lock, flags);
-       if (daemon)
-               md_unregister_thread(daemon); /* destroy the thread */
-}
+       /* the daemon can't stop itself... it'll just exit instead... */
+       if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
+           current->pid != bitmap->writeback_daemon->tsk->pid) {
+               mdk_thread_t *daemon;
+               unsigned long flags;
 
-static void bitmap_stop_daemons(struct bitmap *bitmap)
-{
-       /* the daemons can't stop themselves... they'll just exit instead... */
-       if (bitmap->writeback_daemon &&
-           current->pid != bitmap->writeback_daemon->tsk->pid)
-               bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+               spin_lock_irqsave(&bitmap->lock, flags);
+               daemon = bitmap->writeback_daemon;
+               bitmap->writeback_daemon = NULL;
+               spin_unlock_irqrestore(&bitmap->lock, flags);
+               if (daemon && ! IS_ERR(daemon))
+                       md_unregister_thread(daemon); /* destroy the thread */
+       }
 }
 
 static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1274,9 +1268,16 @@ static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
        }
 }
 
-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors, int behind)
 {
        if (!bitmap) return 0;
+
+       if (behind) {
+               atomic_inc(&bitmap->behind_writes);
+               PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
+                 atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+       }
+
        while (sectors) {
                int blocks;
                bitmap_counter_t *bmc;
@@ -1311,9 +1312,15 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
 }
 
 void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
-                    int success)
+                    int success, int behind)
 {
        if (!bitmap) return;
+       if (behind) {
+               atomic_dec(&bitmap->behind_writes);
+               PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
+                 atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
+       }
+
        while (sectors) {
                int blocks;
                unsigned long flags;
@@ -1424,7 +1431,7 @@ void bitmap_close_sync(struct bitmap *bitmap)
        }
 }
 
-static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
 {
        /* For each chunk covered by any of these sectors, set the
         * counter to 1 and set resync_needed.  They should all
@@ -1441,7 +1448,7 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset)
        }
        if (! *bmc) {
                struct page *page;
-               *bmc = 1 | NEEDED_MASK;
+               *bmc = 1 | (needed?NEEDED_MASK:0);
                bitmap_count_page(bitmap, offset, 1);
                page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
                set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
@@ -1476,17 +1483,14 @@ void bitmap_flush(mddev_t *mddev)
 /*
  * free memory that was allocated
  */
-void bitmap_destroy(mddev_t *mddev)
+static void bitmap_free(struct bitmap *bitmap)
 {
        unsigned long k, pages;
        struct bitmap_page *bp;
-       struct bitmap *bitmap = mddev->bitmap;
 
        if (!bitmap) /* there was no bitmap */
                return;
 
-       mddev->bitmap = NULL; /* disconnect from the md device */
-
        /* release the bitmap file and kill the daemon */
        bitmap_file_put(bitmap);
 
@@ -1504,6 +1508,17 @@ void bitmap_destroy(mddev_t *mddev)
        kfree(bp);
        kfree(bitmap);
 }
+void bitmap_destroy(mddev_t *mddev)
+{
+       struct bitmap *bitmap = mddev->bitmap;
+
+       if (!bitmap) /* there was no bitmap */
+               return;
+
+       mddev->bitmap = NULL; /* disconnect from the md device */
+
+       bitmap_free(bitmap);
+}
 
 /*
  * initialize the bitmap structure
@@ -1517,6 +1532,7 @@ int bitmap_create(mddev_t *mddev)
        unsigned long pages;
        struct file *file = mddev->bitmap_file;
        int err;
+       sector_t start;
 
        BUG_ON(sizeof(bitmap_super_t) != 256);
 
@@ -1533,15 +1549,15 @@ int bitmap_create(mddev_t *mddev)
 
        spin_lock_init(&bitmap->lock);
        bitmap->mddev = mddev;
-       mddev->bitmap = bitmap;
 
        spin_lock_init(&bitmap->write_lock);
        INIT_LIST_HEAD(&bitmap->complete_pages);
        init_waitqueue_head(&bitmap->write_wait);
        bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
                                write_pool_free, NULL);
+       err = -ENOMEM;
        if (!bitmap->write_pool)
-               return -ENOMEM;
+               goto error;
 
        bitmap->file = file;
        bitmap->offset = mddev->bitmap_offset;
@@ -1549,7 +1565,7 @@ int bitmap_create(mddev_t *mddev)
        /* read superblock from bitmap file (this sets bitmap->chunksize) */
        err = bitmap_read_sb(bitmap);
        if (err)
-               return err;
+               goto error;
 
        bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
                                        sizeof(bitmap->chunksize));
@@ -1573,27 +1589,44 @@ int bitmap_create(mddev_t *mddev)
 #else
        bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
 #endif
+       err = -ENOMEM;
        if (!bitmap->bp)
-               return -ENOMEM;
+               goto error;
        memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
 
        bitmap->flags |= BITMAP_ACTIVE;
 
        /* now that we have some pages available, initialize the in-memory
         * bitmap from the on-disk bitmap */
-       err = bitmap_init_from_disk(bitmap);
+       start = 0;
+       if (mddev->degraded == 0
+           || bitmap->events_cleared == mddev->events)
+               /* no need to keep dirty bits to optimise a re-add of a missing device */
+               start = mddev->recovery_cp;
+       err = bitmap_init_from_disk(bitmap, start);
 
        if (err)
-               return err;
+               goto error;
 
        printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
                pages, bmname(bitmap));
 
-       /* kick off the bitmap daemons */
-       err = bitmap_start_daemons(bitmap);
-       if (err)
-               return err;
+       mddev->bitmap = bitmap;
+
+       if (file)
+               /* kick off the bitmap writeback daemon */
+               bitmap->writeback_daemon =
+                       bitmap_start_daemon(bitmap,
+                                           bitmap_writeback_daemon,
+                                           "bitmap_wb");
+
+       if (IS_ERR(bitmap->writeback_daemon))
+               return PTR_ERR(bitmap->writeback_daemon);
        return bitmap_update_sb(bitmap);
+
+ error:
+       bitmap_free(bitmap);
+       return err;
 }
 
 /* the bitmap API -- for raid personalities */
index 17212b4201a156aa7d17040ebeabb339b1af0f42..cc07bbebbb1688156db22c88d746ae54a18b41ee 100644 (file)
@@ -568,12 +568,9 @@ int dm_create_persistent(struct exception_store *store, uint32_t chunk_size)
 
       bad:
        dm_io_put(sectors_to_pages(chunk_size));
-       if (ps) {
-               if (ps->area)
-                       free_area(ps);
-
-               kfree(ps);
-       }
+       if (ps && ps->area)
+               free_area(ps);
+       kfree(ps);
        return r;
 }
 
index b08df8b9b2cad8994a8d5c739c3943f1548cc17d..8632825137538bbb050eadf6cf0c13b101cdc05d 100644 (file)
@@ -375,16 +375,18 @@ static void rh_inc(struct region_hash *rh, region_t region)
 
        read_lock(&rh->hash_lock);
        reg = __rh_find(rh, region);
+
+       atomic_inc(&reg->pending);
+
+       spin_lock_irq(&rh->region_lock);
        if (reg->state == RH_CLEAN) {
                rh->log->type->mark_region(rh->log, reg->key);
 
-               spin_lock_irq(&rh->region_lock);
                reg->state = RH_DIRTY;
                list_del_init(&reg->list);      /* take off the clean list */
-               spin_unlock_irq(&rh->region_lock);
        }
+       spin_unlock_irq(&rh->region_lock);
 
-       atomic_inc(&reg->pending);
        read_unlock(&rh->hash_lock);
 }
 
@@ -408,6 +410,10 @@ static void rh_dec(struct region_hash *rh, region_t region)
 
        if (atomic_dec_and_test(&reg->pending)) {
                spin_lock_irqsave(&rh->region_lock, flags);
+               if (atomic_read(&reg->pending)) { /* check race */
+                       spin_unlock_irqrestore(&rh->region_lock, flags);
+                       return;
+               }
                if (reg->state == RH_RECOVERING) {
                        list_add_tail(&reg->list, &rh->quiesced_regions);
                } else {
index 8d740013d74d5eff047d99f02d1f93d7b65218bd..bb279fad2fd2788e9a8e0d8d8b322df77a76766a 100644 (file)
@@ -38,7 +38,8 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
        /*
         * sector_div(a,b) returns the remainer and sets a to a/b
         */
-       (void)sector_div(block, conf->smallest->size);
+       block >>= conf->preshift;
+       (void)sector_div(block, conf->hash_spacing);
        hash = conf->hash_table[block];
 
        while ((sector>>1) >= (hash->size + hash->offset))
@@ -47,7 +48,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 }
 
 /**
- *     linear_mergeable_bvec -- tell bio layer if two requests can be merged
+ *     linear_mergeable_bvec -- tell bio layer if two requests can be merged
  *     @q: request queue
  *     @bio: the buffer head that's been built up so far
  *     @biovec: the request that could be merged to it.
@@ -116,7 +117,7 @@ static int linear_run (mddev_t *mddev)
        dev_info_t **table;
        mdk_rdev_t *rdev;
        int i, nb_zone, cnt;
-       sector_t start;
+       sector_t min_spacing;
        sector_t curr_offset;
        struct list_head *tmp;
 
@@ -127,11 +128,6 @@ static int linear_run (mddev_t *mddev)
        memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
        mddev->private = conf;
 
-       /*
-        * Find the smallest device.
-        */
-
-       conf->smallest = NULL;
        cnt = 0;
        mddev->array_size = 0;
 
@@ -159,8 +155,6 @@ static int linear_run (mddev_t *mddev)
                disk->size = rdev->size;
                mddev->array_size += rdev->size;
 
-               if (!conf->smallest || (disk->size < conf->smallest->size))
-                       conf->smallest = disk;
                cnt++;
        }
        if (cnt != mddev->raid_disks) {
@@ -168,6 +162,36 @@ static int linear_run (mddev_t *mddev)
                goto out;
        }
 
+       min_spacing = mddev->array_size;
+       sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
+
+       /* min_spacing is the minimum spacing that will fit the hash
+        * table in one PAGE.  This may be much smaller than needed.
+        * We find the smallest non-terminal set of consecutive devices
+        * that is larger than min_spacing as use the size of that as
+        * the actual spacing
+        */
+       conf->hash_spacing = mddev->array_size;
+       for (i=0; i < cnt-1 ; i++) {
+               sector_t sz = 0;
+               int j;
+               for (j=i; i<cnt-1 && sz < min_spacing ; j++)
+                       sz += conf->disks[j].size;
+               if (sz >= min_spacing && sz < conf->hash_spacing)
+                       conf->hash_spacing = sz;
+       }
+
+       /* hash_spacing may be too large for sector_div to work with,
+        * so we might need to pre-shift
+        */
+       conf->preshift = 0;
+       if (sizeof(sector_t) > sizeof(u32)) {
+               sector_t space = conf->hash_spacing;
+               while (space > (sector_t)(~(u32)0)) {
+                       space >>= 1;
+                       conf->preshift++;
+               }
+       }
        /*
         * This code was restructured to work around a gcc-2.95.3 internal
         * compiler error.  Alter it with care.
@@ -177,39 +201,52 @@ static int linear_run (mddev_t *mddev)
                unsigned round;
                unsigned long base;
 
-               sz = mddev->array_size;
-               base = conf->smallest->size;
+               sz = mddev->array_size >> conf->preshift;
+               sz += 1; /* force round-up */
+               base = conf->hash_spacing >> conf->preshift;
                round = sector_div(sz, base);
-               nb_zone = conf->nr_zones = sz + (round ? 1 : 0);
+               nb_zone = sz + (round ? 1 : 0);
        }
-                       
-       conf->hash_table = kmalloc (sizeof (dev_info_t*) * nb_zone,
+       BUG_ON(nb_zone > PAGE_SIZE / sizeof(struct dev_info *));
+
+       conf->hash_table = kmalloc (sizeof (struct dev_info *) * nb_zone,
                                        GFP_KERNEL);
        if (!conf->hash_table)
                goto out;
 
        /*
         * Here we generate the linear hash table
+        * First calculate the device offsets.
         */
+       conf->disks[0].offset = 0;
+       for (i=1; i<mddev->raid_disks; i++)
+               conf->disks[i].offset =
+                       conf->disks[i-1].offset +
+                       conf->disks[i-1].size;
+
        table = conf->hash_table;
-       start = 0;
        curr_offset = 0;
-       for (i = 0; i < cnt; i++) {
-               dev_info_t *disk = conf->disks + i;
+       i = 0;
+       for (curr_offset = 0;
+            curr_offset < mddev->array_size;
+            curr_offset += conf->hash_spacing) {
 
-               disk->offset = curr_offset;
-               curr_offset += disk->size;
+               while (i < mddev->raid_disks-1 &&
+                      curr_offset >= conf->disks[i+1].offset)
+                       i++;
 
-               /* 'curr_offset' is the end of this disk
-                * 'start' is the start of table
+               *table ++ = conf->disks + i;
+       }
+
+       if (conf->preshift) {
+               conf->hash_spacing >>= conf->preshift;
+               /* round hash_spacing up so that when we divide by it,
+                * we err on the side of "too-low", which is safest.
                 */
-               while (start < curr_offset) {
-                       *table++ = disk;
-                       start += conf->smallest->size;
-               }
+               conf->hash_spacing++;
        }
-       if (table-conf->hash_table != nb_zone)
-               BUG();
+
+       BUG_ON(table - conf->hash_table > nb_zone);
 
        blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
        mddev->queue->unplug_fn = linear_unplug;
@@ -238,6 +275,11 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
        dev_info_t *tmp_dev;
        sector_t block;
 
+       if (unlikely(bio_barrier(bio))) {
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        if (bio_data_dir(bio)==WRITE) {
                disk_stat_inc(mddev->gendisk, writes);
                disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
@@ -294,7 +336,7 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
        sector_t s = 0;
   
        seq_printf(seq, "      ");
-       for (j = 0; j < conf->nr_zones; j++)
+       for (j = 0; j < mddev->raid_disks; j++)
        {
                char b[BDEVNAME_SIZE];
                s += conf->smallest_size;
index 20ca80b7dc20611de86d418faf8da69140fd764a..2897df90df44856df8d769bbc4f305543425aaf6 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <linux/module.h>
 #include <linux/config.h>
+#include <linux/kthread.h>
 #include <linux/linkage.h>
 #include <linux/raid/md.h>
 #include <linux/raid/bitmap.h>
@@ -73,7 +74,7 @@ static DEFINE_SPINLOCK(pers_lock);
  * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit'
  * is 1000 KB/sec, so the extra system load does not show up that much.
  * Increase it if you want to have more _guaranteed_ speed. Note that
- * the RAID driver will use the maximum available bandwith if the IO
+ * the RAID driver will use the maximum available bandwidth if the IO
  * subsystem is idle. There is also an 'absolute maximum' reconstruction
  * speed limit - in case reconstruction slows down your system despite
  * idle IO detection.
@@ -393,7 +394,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
        return ret;
 }
 
-static int read_disk_sb(mdk_rdev_t * rdev)
+static int read_disk_sb(mdk_rdev_t * rdev, int size)
 {
        char b[BDEVNAME_SIZE];
        if (!rdev->sb_page) {
@@ -404,7 +405,7 @@ static int read_disk_sb(mdk_rdev_t * rdev)
                return 0;
 
 
-       if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
+       if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
                goto fail;
        rdev->sb_loaded = 1;
        return 0;
@@ -531,7 +532,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
        sb_offset = calc_dev_sboffset(rdev->bdev);
        rdev->sb_offset = sb_offset;
 
-       ret = read_disk_sb(rdev);
+       ret = read_disk_sb(rdev, MD_SB_BYTES);
        if (ret) return ret;
 
        ret = -EINVAL;
@@ -564,6 +565,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 
        rdev->preferred_minor = sb->md_minor;
        rdev->data_offset = 0;
+       rdev->sb_size = MD_SB_BYTES;
 
        if (sb->level == LEVEL_MULTIPATH)
                rdev->desc_nr = -1;
@@ -623,6 +625,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->size = sb->size;
                mddev->events = md_event(sb);
                mddev->bitmap_offset = 0;
+               mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
 
                if (sb->state & (1<<MD_SB_CLEAN))
                        mddev->recovery_cp = MaxSector;
@@ -643,12 +646,12 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 
                if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
                    mddev->bitmap_file == NULL) {
-                       if (mddev->level != 1) {
+                       if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
                                /* FIXME use a better test */
                                printk(KERN_WARNING "md: bitmaps only support for raid1\n");
                                return -EINVAL;
                        }
-                       mddev->bitmap_offset = (MD_SB_BYTES >> 9);
+                       mddev->bitmap_offset = mddev->default_bitmap_offset;
                }
 
        } else if (mddev->pers == NULL) {
@@ -669,6 +672,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 
        if (mddev->level != LEVEL_MULTIPATH) {
                rdev->faulty = 0;
+               rdev->flags = 0;
                desc = sb->disks + rdev->desc_nr;
 
                if (desc->state & (1<<MD_DISK_FAULTY))
@@ -678,6 +682,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                        rdev->in_sync = 1;
                        rdev->raid_disk = desc->raid_disk;
                }
+               if (desc->state & (1<<MD_DISK_WRITEMOSTLY))
+                       set_bit(WriteMostly, &rdev->flags);
        } else /* MULTIPATH are always insync */
                rdev->in_sync = 1;
        return 0;
@@ -706,6 +712,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
        int i;
        int active=0, working=0,failed=0,spare=0,nr_disks=0;
 
+       rdev->sb_size = MD_SB_BYTES;
+
        sb = (mdp_super_t*)page_address(rdev->sb_page);
 
        memset(sb, 0, sizeof(*sb));
@@ -776,6 +784,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
                        spare++;
                        working++;
                }
+               if (test_bit(WriteMostly, &rdev2->flags))
+                       d->state |= (1<<MD_DISK_WRITEMOSTLY);
        }
        
        /* now set the "removed" and "faulty" bits on any missing devices */
@@ -831,6 +841,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
        int ret;
        sector_t sb_offset;
        char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
+       int bmask;
 
        /*
         * Calculate the position of the superblock.
@@ -859,7 +870,10 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
        }
        rdev->sb_offset = sb_offset;
 
-       ret = read_disk_sb(rdev);
+       /* superblock is rarely larger than 1K, but it can be larger,
+        * and it is safe to read 4k, so we do that
+        */
+       ret = read_disk_sb(rdev, 4096);
        if (ret) return ret;
 
 
@@ -869,7 +883,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
            sb->major_version != cpu_to_le32(1) ||
            le32_to_cpu(sb->max_dev) > (4096-256)/2 ||
            le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) ||
-           sb->feature_map != 0)
+           (le32_to_cpu(sb->feature_map) & ~MD_FEATURE_ALL) != 0)
                return -EINVAL;
 
        if (calc_sb_1_csum(sb) != sb->sb_csum) {
@@ -885,6 +899,11 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
        rdev->preferred_minor = 0xffff;
        rdev->data_offset = le64_to_cpu(sb->data_offset);
 
+       rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
+       bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
+       if (rdev->sb_size & bmask)
+               rdev-> sb_size = (rdev->sb_size | bmask)+1;
+
        if (refdev == 0)
                return 1;
        else {
@@ -939,13 +958,15 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->size = le64_to_cpu(sb->size)/2;
                mddev->events = le64_to_cpu(sb->events);
                mddev->bitmap_offset = 0;
+               mddev->default_bitmap_offset = 0;
+               mddev->default_bitmap_offset = 1024;
                
                mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
                memcpy(mddev->uuid, sb->set_uuid, 16);
 
                mddev->max_disks =  (4096-256)/2;
 
-               if ((le32_to_cpu(sb->feature_map) & 1) &&
+               if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) &&
                    mddev->bitmap_file == NULL ) {
                        if (mddev->level != 1) {
                                printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
@@ -986,6 +1007,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                        rdev->raid_disk = role;
                        break;
                }
+               rdev->flags = 0;
+               if (sb->devflags & WriteMostly1)
+                       set_bit(WriteMostly, &rdev->flags);
        } else /* MULTIPATH are always insync */
                rdev->in_sync = 1;
 
@@ -1017,7 +1041,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 
        if (mddev->bitmap && mddev->bitmap_file == NULL) {
                sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
-               sb->feature_map = cpu_to_le32(1);
+               sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
        }
 
        max_dev = 0;
@@ -1363,7 +1387,7 @@ repeat:
                dprintk("%s ", bdevname(rdev->bdev,b));
                if (!rdev->faulty) {
                        md_super_write(mddev,rdev,
-                                      rdev->sb_offset<<1, MD_SB_BYTES,
+                                      rdev->sb_offset<<1, rdev->sb_size,
                                       rdev->sb_page);
                        dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
                                bdevname(rdev->bdev,b),
@@ -2073,6 +2097,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
        info.state         = 0;
        if (mddev->in_sync)
                info.state = (1<<MD_SB_CLEAN);
+       if (mddev->bitmap && mddev->bitmap_offset)
+               info.state = (1<<MD_SB_BITMAP_PRESENT);
        info.active_disks  = active;
        info.working_disks = working;
        info.failed_disks  = failed;
@@ -2087,7 +2113,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
        return 0;
 }
 
-static int get_bitmap_file(mddev_t * mddev, void * arg)
+static int get_bitmap_file(mddev_t * mddev, void __user * arg)
 {
        mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
        char *ptr, *buf = NULL;
@@ -2146,6 +2172,8 @@ static int get_disk_info(mddev_t * mddev, void __user * arg)
                        info.state |= (1<<MD_DISK_ACTIVE);
                        info.state |= (1<<MD_DISK_SYNC);
                }
+               if (test_bit(WriteMostly, &rdev->flags))
+                       info.state |= (1<<MD_DISK_WRITEMOSTLY);
        } else {
                info.major = info.minor = 0;
                info.raid_disk = -1;
@@ -2210,8 +2238,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                               mdname(mddev));
                        return -EINVAL;
                }
-               rdev = md_import_device(dev, mddev->major_version,
-                                       mddev->minor_version);
+               if (mddev->persistent)
+                       rdev = md_import_device(dev, mddev->major_version,
+                                               mddev->minor_version);
+               else
+                       rdev = md_import_device(dev, -1, -1);
                if (IS_ERR(rdev)) {
                        printk(KERN_WARNING 
                                "md: md_import_device returned %ld\n",
@@ -2231,6 +2262,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                rdev->saved_raid_disk = rdev->raid_disk;
 
                rdev->in_sync = 0; /* just to be sure */
+               if (info->state & (1<<MD_DISK_WRITEMOSTLY))
+                       set_bit(WriteMostly, &rdev->flags);
+
                rdev->raid_disk = -1;
                err = bind_rdev_to_array(rdev, mddev);
                if (err)
@@ -2271,6 +2305,9 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                else
                        rdev->in_sync = 0;
 
+               if (info->state & (1<<MD_DISK_WRITEMOSTLY))
+                       set_bit(WriteMostly, &rdev->flags);
+
                err = bind_rdev_to_array(rdev, mddev);
                if (err) {
                        export_rdev(rdev);
@@ -2430,25 +2467,51 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
 {
        int err;
 
-       if (mddev->pers)
-               return -EBUSY;
+       if (mddev->pers) {
+               if (!mddev->pers->quiesce)
+                       return -EBUSY;
+               if (mddev->recovery || mddev->sync_thread)
+                       return -EBUSY;
+               /* we should be able to change the bitmap.. */
+       }
 
-       mddev->bitmap_file = fget(fd);
 
-       if (mddev->bitmap_file == NULL) {
-               printk(KERN_ERR "%s: error: failed to get bitmap file\n",
-                       mdname(mddev));
-               return -EBADF;
-       }
+       if (fd >= 0) {
+               if (mddev->bitmap)
+                       return -EEXIST; /* cannot add when bitmap is present */
+               mddev->bitmap_file = fget(fd);
 
-       err = deny_bitmap_write_access(mddev->bitmap_file);
-       if (err) {
-               printk(KERN_ERR "%s: error: bitmap file is already in use\n",
-                       mdname(mddev));
-               fput(mddev->bitmap_file);
-               mddev->bitmap_file = NULL;
-       } else
+               if (mddev->bitmap_file == NULL) {
+                       printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+                              mdname(mddev));
+                       return -EBADF;
+               }
+
+               err = deny_bitmap_write_access(mddev->bitmap_file);
+               if (err) {
+                       printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+                              mdname(mddev));
+                       fput(mddev->bitmap_file);
+                       mddev->bitmap_file = NULL;
+                       return err;
+               }
                mddev->bitmap_offset = 0; /* file overrides offset */
+       } else if (mddev->bitmap == NULL)
+               return -ENOENT; /* cannot remove what isn't there */
+       err = 0;
+       if (mddev->pers) {
+               mddev->pers->quiesce(mddev, 1);
+               if (fd >= 0)
+                       err = bitmap_create(mddev);
+               if (fd < 0 || err)
+                       bitmap_destroy(mddev);
+               mddev->pers->quiesce(mddev, 0);
+       } else if (fd < 0) {
+               if (mddev->bitmap_file)
+                       fput(mddev->bitmap_file);
+               mddev->bitmap_file = NULL;
+       }
+
        return err;
 }
 
@@ -2528,6 +2591,11 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
 {
        int rv = 0;
        int cnt = 0;
+       int state = 0;
+
+       /* calculate expected state,ignoring low bits */
+       if (mddev->bitmap && mddev->bitmap_offset)
+               state |= (1 << MD_SB_BITMAP_PRESENT);
 
        if (mddev->major_version != info->major_version ||
            mddev->minor_version != info->minor_version ||
@@ -2536,12 +2604,16 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
            mddev->level         != info->level         ||
 /*         mddev->layout        != info->layout        || */
            !mddev->persistent   != info->not_persistent||
-           mddev->chunk_size    != info->chunk_size    )
+           mddev->chunk_size    != info->chunk_size    ||
+           /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
+           ((state^info->state) & 0xfffffe00)
+               )
                return -EINVAL;
        /* Check there is only one change */
        if (mddev->size != info->size) cnt++;
        if (mddev->raid_disks != info->raid_disks) cnt++;
        if (mddev->layout != info->layout) cnt++;
+       if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++;
        if (cnt == 0) return 0;
        if (cnt > 1) return -EINVAL;
 
@@ -2620,6 +2692,35 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
                        }
                }
        }
+       if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
+               if (mddev->pers->quiesce == NULL)
+                       return -EINVAL;
+               if (mddev->recovery || mddev->sync_thread)
+                       return -EBUSY;
+               if (info->state & (1<<MD_SB_BITMAP_PRESENT)) {
+                       /* add the bitmap */
+                       if (mddev->bitmap)
+                               return -EEXIST;
+                       if (mddev->default_bitmap_offset == 0)
+                               return -EINVAL;
+                       mddev->bitmap_offset = mddev->default_bitmap_offset;
+                       mddev->pers->quiesce(mddev, 1);
+                       rv = bitmap_create(mddev);
+                       if (rv)
+                               bitmap_destroy(mddev);
+                       mddev->pers->quiesce(mddev, 0);
+               } else {
+                       /* remove the bitmap */
+                       if (!mddev->bitmap)
+                               return -ENOENT;
+                       if (mddev->bitmap->file)
+                               return -EINVAL;
+                       mddev->pers->quiesce(mddev, 1);
+                       bitmap_destroy(mddev);
+                       mddev->pers->quiesce(mddev, 0);
+                       mddev->bitmap_offset = 0;
+               }
+       }
        md_update_sb(mddev);
        return rv;
 }
@@ -2781,7 +2882,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
                        goto done_unlock;
 
                case GET_BITMAP_FILE:
-                       err = get_bitmap_file(mddev, (void *)arg);
+                       err = get_bitmap_file(mddev, argp);
                        goto done_unlock;
 
                case GET_DISK_INFO:
@@ -2950,18 +3051,6 @@ static int md_thread(void * arg)
 {
        mdk_thread_t *thread = arg;
 
-       lock_kernel();
-
-       /*
-        * Detach thread
-        */
-
-       daemonize(thread->name, mdname(thread->mddev));
-
-       current->exit_signal = SIGCHLD;
-       allow_signal(SIGKILL);
-       thread->tsk = current;
-
        /*
         * md_thread is a 'system-thread', it's priority should be very
         * high. We avoid resource deadlocks individually in each
@@ -2973,14 +3062,14 @@ static int md_thread(void * arg)
         * bdflush, otherwise bdflush will deadlock if there are too
         * many dirty RAID5 blocks.
         */
-       unlock_kernel();
 
        complete(thread->event);
-       while (thread->run) {
+       while (!kthread_should_stop()) {
                void (*run)(mddev_t *);
 
                wait_event_interruptible_timeout(thread->wqueue,
-                                                test_bit(THREAD_WAKEUP, &thread->flags),
+                                                test_bit(THREAD_WAKEUP, &thread->flags)
+                                                || kthread_should_stop(),
                                                 thread->timeout);
                try_to_freeze();
 
@@ -2989,11 +3078,8 @@ static int md_thread(void * arg)
                run = thread->run;
                if (run)
                        run(thread->mddev);
-
-               if (signal_pending(current))
-                       flush_signals(current);
        }
-       complete(thread->event);
+
        return 0;
 }
 
@@ -3010,11 +3096,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
                                 const char *name)
 {
        mdk_thread_t *thread;
-       int ret;
        struct completion event;
 
-       thread = (mdk_thread_t *) kmalloc
-                               (sizeof(mdk_thread_t), GFP_KERNEL);
+       thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
        if (!thread)
                return NULL;
 
@@ -3027,8 +3111,8 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
        thread->mddev = mddev;
        thread->name = name;
        thread->timeout = MAX_SCHEDULE_TIMEOUT;
-       ret = kernel_thread(md_thread, thread, 0);
-       if (ret < 0) {
+       thread->tsk = kthread_run(md_thread, thread, mdname(thread->mddev));
+       if (IS_ERR(thread->tsk)) {
                kfree(thread);
                return NULL;
        }
@@ -3038,21 +3122,9 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
 
 void md_unregister_thread(mdk_thread_t *thread)
 {
-       struct completion event;
-
-       init_completion(&event);
-
-       thread->event = &event;
-
-       /* As soon as ->run is set to NULL, the task could disappear,
-        * so we need to hold tasklist_lock until we have sent the signal
-        */
        dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
-       read_lock(&tasklist_lock);
-       thread->run = NULL;
-       send_sig(SIGKILL, thread->tsk, 1);
-       read_unlock(&tasklist_lock);
-       wait_for_completion(&event);
+
+       kthread_stop(thread->tsk);
        kfree(thread);
 }
 
@@ -3259,10 +3331,13 @@ static int md_seq_show(struct seq_file *seq, void *v)
                        char b[BDEVNAME_SIZE];
                        seq_printf(seq, " %s[%d]",
                                bdevname(rdev->bdev,b), rdev->desc_nr);
+                       if (test_bit(WriteMostly, &rdev->flags))
+                               seq_printf(seq, "(W)");
                        if (rdev->faulty) {
                                seq_printf(seq, "(F)");
                                continue;
-                       }
+                       } else if (rdev->raid_disk < 0)
+                               seq_printf(seq, "(S)"); /* spare */
                        size += rdev->size;
                }
 
@@ -3274,6 +3349,15 @@ static int md_seq_show(struct seq_file *seq, void *v)
                                seq_printf(seq, "\n      %llu blocks",
                                        (unsigned long long)size);
                }
+               if (mddev->persistent) {
+                       if (mddev->major_version != 0 ||
+                           mddev->minor_version != 90) {
+                               seq_printf(seq," super %d.%d",
+                                          mddev->major_version,
+                                          mddev->minor_version);
+                       }
+               } else
+                       seq_printf(seq, " super non-persistent");
 
                if (mddev->pers) {
                        mddev->pers->status (seq, mddev);
@@ -3416,7 +3500,6 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
  */
 void md_write_start(mddev_t *mddev, struct bio *bi)
 {
-       DEFINE_WAIT(w);
        if (bio_data_dir(bi) != WRITE)
                return;
 
@@ -3533,7 +3616,7 @@ static void md_do_sync(mddev_t *mddev)
        printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
        printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
                " %d KB/sec/disc.\n", sysctl_speed_limit_min);
-       printk(KERN_INFO "md: using maximum available idle IO bandwith "
+       printk(KERN_INFO "md: using maximum available idle IO bandwidth "
               "(but not more than %d KB/sec) for reconstruction.\n",
               sysctl_speed_limit_max);
 
index 2d2ca7fa0265261a71e2493e88b68403cc902c57..286342375fb7f84d5d400e28755e4347f7e99035 100644 (file)
@@ -169,6 +169,11 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
        struct multipath_bh * mp_bh;
        struct multipath_info *multipath;
 
+       if (unlikely(bio_barrier(bio))) {
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        mp_bh = mempool_alloc(conf->pool, GFP_NOIO);
 
        mp_bh->master_bio = bio;
index 2120710172c5411a4743686762878a76e8aa7695..f6757259ce7fe3f8ced8b05553f2cf52c25e6dbb 100644 (file)
@@ -404,6 +404,11 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
        unsigned long chunk;
        sector_t block, rsect;
 
+       if (unlikely(bio_barrier(bio))) {
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        if (bio_data_dir(bio)==WRITE) {
                disk_stat_inc(mddev->gendisk, writes);
                disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio));
index 51d9645ed09c5e8ff79aa9e7a6604e94dc274a54..a93ca478142a2c325b78e5790b55455853ad44ec 100644 (file)
@@ -222,8 +222,17 @@ static void raid_end_bio_io(r1bio_t *r1_bio)
 {
        struct bio *bio = r1_bio->master_bio;
 
-       bio_endio(bio, bio->bi_size,
-               test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+       /* if nobody has done the final endio yet, do it now */
+       if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+               PRINTK(KERN_DEBUG "raid1: sync end %s on sectors %llu-%llu\n",
+                       (bio_data_dir(bio) == WRITE) ? "write" : "read",
+                       (unsigned long long) bio->bi_sector,
+                       (unsigned long long) bio->bi_sector +
+                               (bio->bi_size >> 9) - 1);
+
+               bio_endio(bio, bio->bi_size,
+                       test_bit(R1BIO_Uptodate, &r1_bio->state) ? 0 : -EIO);
+       }
        free_r1bio(r1_bio);
 }
 
@@ -292,7 +301,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
 {
        int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
        r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
-       int mirror;
+       int mirror, behind;
        conf_t *conf = mddev_to_conf(r1_bio->mddev);
 
        if (bio->bi_size)
@@ -323,16 +332,46 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
 
        update_head_pos(mirror, r1_bio);
 
+       behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
+       if (behind) {
+               if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+                       atomic_dec(&r1_bio->behind_remaining);
+
+               /* In behind mode, we ACK the master bio once the I/O has safely
+                * reached all non-writemostly disks. Setting the Returned bit
+                * ensures that this gets done only once -- we don't ever want to
+                * return -EIO here, instead we'll wait */
+
+               if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
+                   test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+                       /* Maybe we can return now */
+                       if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
+                               struct bio *mbio = r1_bio->master_bio;
+                               PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n",
+                                      (unsigned long long) mbio->bi_sector,
+                                      (unsigned long long) mbio->bi_sector +
+                                      (mbio->bi_size >> 9) - 1);
+                               bio_endio(mbio, mbio->bi_size, 0);
+                       }
+               }
+       }
        /*
         *
         * Let's see if all mirrored write operations have finished
         * already.
         */
        if (atomic_dec_and_test(&r1_bio->remaining)) {
+               if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+                       /* free extra copy of the data pages */
+                       int i = bio->bi_vcnt;
+                       while (i--)
+                               __free_page(bio->bi_io_vec[i].bv_page);
+               }
                /* clear the bitmap if all writes complete successfully */
                bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
                                r1_bio->sectors,
-                               !test_bit(R1BIO_Degraded, &r1_bio->state));
+                               !test_bit(R1BIO_Degraded, &r1_bio->state),
+                               behind);
                md_write_end(r1_bio->mddev);
                raid_end_bio_io(r1_bio);
        }
@@ -360,13 +399,14 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 {
        const unsigned long this_sector = r1_bio->sector;
        int new_disk = conf->last_used, disk = new_disk;
+       int wonly_disk = -1;
        const int sectors = r1_bio->sectors;
        sector_t new_distance, current_distance;
-       mdk_rdev_t *new_rdev, *rdev;
+       mdk_rdev_t *rdev;
 
        rcu_read_lock();
        /*
-        * Check if it if we can balance. We can balance on the whole
+        * Check if we can balance. We can balance on the whole
         * device if no resync is going on, or below the resync window.
         * We take the first readable disk when above the resync window.
         */
@@ -376,11 +416,16 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
                /* Choose the first operation device, for consistancy */
                new_disk = 0;
 
-               while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
-                      !new_rdev->in_sync) {
-                       new_disk++;
-                       if (new_disk == conf->raid_disks) {
-                               new_disk = -1;
+               for (rdev = conf->mirrors[new_disk].rdev;
+                    !rdev || !rdev->in_sync
+                            || test_bit(WriteMostly, &rdev->flags);
+                    rdev = conf->mirrors[++new_disk].rdev) {
+
+                       if (rdev && rdev->in_sync)
+                               wonly_disk = new_disk;
+
+                       if (new_disk == conf->raid_disks - 1) {
+                               new_disk = wonly_disk;
                                break;
                        }
                }
@@ -389,16 +434,26 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 
 
        /* make sure the disk is operational */
-       while ((new_rdev=conf->mirrors[new_disk].rdev) == NULL ||
-              !new_rdev->in_sync) {
+       for (rdev = conf->mirrors[new_disk].rdev;
+            !rdev || !rdev->in_sync ||
+                    test_bit(WriteMostly, &rdev->flags);
+            rdev = conf->mirrors[new_disk].rdev) {
+
+               if (rdev && rdev->in_sync)
+                       wonly_disk = new_disk;
+
                if (new_disk <= 0)
                        new_disk = conf->raid_disks;
                new_disk--;
                if (new_disk == disk) {
-                       new_disk = -1;
-                       goto rb_out;
+                       new_disk = wonly_disk;
+                       break;
                }
        }
+
+       if (new_disk < 0)
+               goto rb_out;
+
        disk = new_disk;
        /* now disk == new_disk == starting point for search */
 
@@ -419,37 +474,41 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
                        disk = conf->raid_disks;
                disk--;
 
-               if ((rdev=conf->mirrors[disk].rdev) == NULL ||
-                   !rdev->in_sync)
+               rdev = conf->mirrors[disk].rdev;
+
+               if (!rdev ||
+                   !rdev->in_sync ||
+                   test_bit(WriteMostly, &rdev->flags))
                        continue;
 
                if (!atomic_read(&rdev->nr_pending)) {
                        new_disk = disk;
-                       new_rdev = rdev;
                        break;
                }
                new_distance = abs(this_sector - conf->mirrors[disk].head_position);
                if (new_distance < current_distance) {
                        current_distance = new_distance;
                        new_disk = disk;
-                       new_rdev = rdev;
                }
        } while (disk != conf->last_used);
 
-rb_out:
+ rb_out:
 
 
        if (new_disk >= 0) {
-               conf->next_seq_sect = this_sector + sectors;
-               conf->last_used = new_disk;
-               atomic_inc(&new_rdev->nr_pending);
-               if (!new_rdev->in_sync) {
+               rdev = conf->mirrors[new_disk].rdev;
+               if (!rdev)
+                       goto retry;
+               atomic_inc(&rdev->nr_pending);
+               if (!rdev->in_sync) {
                        /* cannot risk returning a device that failed
                         * before we inc'ed nr_pending
                         */
-                       atomic_dec(&new_rdev->nr_pending);
+                       atomic_dec(&rdev->nr_pending);
                        goto retry;
                }
+               conf->next_seq_sect = this_sector + sectors;
+               conf->last_used = new_disk;
        }
        rcu_read_unlock();
 
@@ -542,6 +601,39 @@ static void device_barrier(conf_t *conf, sector_t sect)
        spin_unlock_irq(&conf->resync_lock);
 }
 
+/* duplicate the data pages for behind I/O */
+static struct page **alloc_behind_pages(struct bio *bio)
+{
+       int i;
+       struct bio_vec *bvec;
+       struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *),
+                                       GFP_NOIO);
+       if (unlikely(!pages))
+               goto do_sync_io;
+
+       memset(pages, 0, bio->bi_vcnt * sizeof(struct page *));
+
+       bio_for_each_segment(bvec, bio, i) {
+               pages[i] = alloc_page(GFP_NOIO);
+               if (unlikely(!pages[i]))
+                       goto do_sync_io;
+               memcpy(kmap(pages[i]) + bvec->bv_offset,
+                       kmap(bvec->bv_page) + bvec->bv_offset, bvec->bv_len);
+               kunmap(pages[i]);
+               kunmap(bvec->bv_page);
+       }
+
+       return pages;
+
+do_sync_io:
+       if (pages)
+               for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
+                       __free_page(pages[i]);
+       kfree(pages);
+       PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
+       return NULL;
+}
+
 static int make_request(request_queue_t *q, struct bio * bio)
 {
        mddev_t *mddev = q->queuedata;
@@ -554,7 +646,12 @@ static int make_request(request_queue_t *q, struct bio * bio)
        struct bitmap *bitmap = mddev->bitmap;
        unsigned long flags;
        struct bio_list bl;
+       struct page **behind_pages = NULL;
 
+       if (unlikely(bio_barrier(bio))) {
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
 
        /*
         * Register the new request and wait if the reconstruction
@@ -589,8 +686,6 @@ static int make_request(request_queue_t *q, struct bio * bio)
        r1_bio->mddev = mddev;
        r1_bio->sector = bio->bi_sector;
 
-       r1_bio->state = 0;
-
        if (bio_data_dir(bio) == READ) {
                /*
                 * read balancing logic:
@@ -651,13 +746,22 @@ static int make_request(request_queue_t *q, struct bio * bio)
        }
        rcu_read_unlock();
 
+       BUG_ON(targets == 0); /* we never fail the last device */
+
        if (targets < conf->raid_disks) {
                /* array is degraded, we will not clear the bitmap
                 * on I/O completion (see raid1_end_write_request) */
                set_bit(R1BIO_Degraded, &r1_bio->state);
        }
 
+       /* do behind I/O ? */
+       if (bitmap &&
+           atomic_read(&bitmap->behind_writes) < bitmap->max_write_behind &&
+           (behind_pages = alloc_behind_pages(bio)) != NULL)
+               set_bit(R1BIO_BehindIO, &r1_bio->state);
+
        atomic_set(&r1_bio->remaining, 0);
+       atomic_set(&r1_bio->behind_remaining, 0);
 
        bio_list_init(&bl);
        for (i = 0; i < disks; i++) {
@@ -674,12 +778,31 @@ static int make_request(request_queue_t *q, struct bio * bio)
                mbio->bi_rw = WRITE;
                mbio->bi_private = r1_bio;
 
+               if (behind_pages) {
+                       struct bio_vec *bvec;
+                       int j;
+
+                       /* Yes, I really want the '__' version so that
+                        * we clear any unused pointer in the io_vec, rather
+                        * than leave them unchanged.  This is important
+                        * because when we come to free the pages, we won't
+                        * know the originial bi_idx, so we just free
+                        * them all
+                        */
+                       __bio_for_each_segment(bvec, mbio, j, 0)
+                               bvec->bv_page = behind_pages[j];
+                       if (test_bit(WriteMostly, &conf->mirrors[i].rdev->flags))
+                               atomic_inc(&r1_bio->behind_remaining);
+               }
+
                atomic_inc(&r1_bio->remaining);
 
                bio_list_add(&bl, mbio);
        }
+       kfree(behind_pages); /* the behind pages are attached to the bios now */
 
-       bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
+       bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors,
+                               test_bit(R1BIO_BehindIO, &r1_bio->state));
        spin_lock_irqsave(&conf->device_lock, flags);
        bio_list_merge(&conf->pending_bio_list, &bl);
        bio_list_init(&bl);
@@ -1105,6 +1228,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        sector_t max_sector, nr_sectors;
        int disk;
        int i;
+       int wonly;
        int write_targets = 0;
        int sync_blocks;
        int still_degraded = 0;
@@ -1160,14 +1284,21 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
         */
        disk = conf->last_used;
        /* make sure disk is operational */
-
+       wonly = disk;
        while (conf->mirrors[disk].rdev == NULL ||
-              !conf->mirrors[disk].rdev->in_sync) {
+              !conf->mirrors[disk].rdev->in_sync ||
+              test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
+               ) {
+               if (conf->mirrors[disk].rdev  &&
+                   conf->mirrors[disk].rdev->in_sync)
+                       wonly = disk;
                if (disk <= 0)
                        disk = conf->raid_disks;
                disk--;
-               if (disk == conf->last_used)
+               if (disk == conf->last_used) {
+                       disk = wonly;
                        break;
+               }
        }
        conf->last_used = disk;
        atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
@@ -1439,6 +1570,17 @@ out:
 static int stop(mddev_t *mddev)
 {
        conf_t *conf = mddev_to_conf(mddev);
+       struct bitmap *bitmap = mddev->bitmap;
+       int behind_wait = 0;
+
+       /* wait for behind writes to complete */
+       while (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+               behind_wait++;
+               printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(HZ); /* wait a second */
+               /* need to kick something here to make sure I/O goes? */
+       }
 
        md_unregister_thread(mddev->thread);
        mddev->thread = NULL;
@@ -1561,6 +1703,35 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
        return 0;
 }
 
+static void raid1_quiesce(mddev_t *mddev, int state)
+{
+       conf_t *conf = mddev_to_conf(mddev);
+
+       switch(state) {
+       case 1:
+               spin_lock_irq(&conf->resync_lock);
+               conf->barrier++;
+               wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
+                                   conf->resync_lock, raid1_unplug(mddev->queue));
+               spin_unlock_irq(&conf->resync_lock);
+               break;
+       case 0:
+               spin_lock_irq(&conf->resync_lock);
+               conf->barrier--;
+               spin_unlock_irq(&conf->resync_lock);
+               wake_up(&conf->wait_resume);
+               wake_up(&conf->wait_idle);
+               break;
+       }
+       if (mddev->thread) {
+               if (mddev->bitmap)
+                       mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+               else
+                       mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+               md_wakeup_thread(mddev->thread);
+       }
+}
+
 
 static mdk_personality_t raid1_personality =
 {
@@ -1577,6 +1748,7 @@ static mdk_personality_t raid1_personality =
        .sync_request   = sync_request,
        .resize         = raid1_resize,
        .reshape        = raid1_reshape,
+       .quiesce        = raid1_quiesce,
 };
 
 static int __init raid_init(void)
index 62ebb1bc72be24cc32ecc775c5bd71603d44e5c6..5bd1e9ec899d8b23f02d498664ca7d29c76a9a7c 100644 (file)
@@ -538,7 +538,8 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
        }
 
 
-       current_distance = abs(this_sector - conf->mirrors[disk].head_position);
+       current_distance = abs(r10_bio->devs[slot].addr -
+                              conf->mirrors[disk].head_position);
 
        /* Find the disk whose head is closest */
 
@@ -668,6 +669,11 @@ static int make_request(request_queue_t *q, struct bio * bio)
        int i;
        int chunk_sects = conf->chunk_mask + 1;
 
+       if (unlikely(bio_barrier(bio))) {
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        /* If this request crosses a chunk boundary, we need to
         * split it.  This will only happen for 1 PAGE (or less) requests.
         */
@@ -900,6 +906,27 @@ static void close_sync(conf_t *conf)
        conf->r10buf_pool = NULL;
 }
 
+/* check if there are enough drives for
+ * every block to appear on atleast one
+ */
+static int enough(conf_t *conf)
+{
+       int first = 0;
+
+       do {
+               int n = conf->copies;
+               int cnt = 0;
+               while (n--) {
+                       if (conf->mirrors[first].rdev)
+                               cnt++;
+                       first = (first+1) % conf->raid_disks;
+               }
+               if (cnt == 0)
+                       return 0;
+       } while (first != 0);
+       return 1;
+}
+
 static int raid10_spare_active(mddev_t *mddev)
 {
        int i;
@@ -938,6 +965,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                 * very different from resync
                 */
                return 0;
+       if (!enough(conf))
+               return 0;
 
        for (mirror=0; mirror < mddev->raid_disks; mirror++)
                if ( !(p=conf->mirrors+mirror)->rdev) {
@@ -1445,7 +1474,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                                        }
                                }
                                if (j == conf->copies) {
-                                       BUG();
+                                       /* Cannot recover, so abort the recovery */
+                                       put_buf(r10_bio);
+                                       r10_bio = rb2;
+                                       if (!test_and_set_bit(MD_RECOVERY_ERR, &mddev->recovery))
+                                               printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n",
+                                                      mdname(mddev));
+                                       break;
                                }
                        }
                if (biolist == NULL) {
@@ -1678,9 +1713,10 @@ static int run(mddev_t *mddev)
        init_waitqueue_head(&conf->wait_idle);
        init_waitqueue_head(&conf->wait_resume);
 
-       if (!conf->working_disks) {
-               printk(KERN_ERR "raid10: no operational mirrors for %s\n",
-                       mdname(mddev));
+       /* need to check that every block has at least one working mirror */
+       if (!enough(conf)) {
+               printk(KERN_ERR "raid10: not enough operational mirrors for %s\n",
+                      mdname(mddev));
                goto out_free_conf;
        }
 
index 43f231a467d5cb0137f15bd5568de80993a0bb08..4683ca24c0469d0fccbfb56d33396f78d1278baf 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/bitops.h>
 #include <asm/atomic.h>
 
+#include <linux/raid/bitmap.h>
+
 /*
  * Stripe cache
  */
@@ -79,8 +81,13 @@ static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
                if (test_bit(STRIPE_HANDLE, &sh->state)) {
                        if (test_bit(STRIPE_DELAYED, &sh->state))
                                list_add_tail(&sh->lru, &conf->delayed_list);
-                       else
+                       else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+                                conf->seq_write == sh->bm_seq)
+                               list_add_tail(&sh->lru, &conf->bitmap_list);
+                       else {
+                               clear_bit(STRIPE_BIT_DELAY, &sh->state);
                                list_add_tail(&sh->lru, &conf->handle_list);
+                       }
                        md_wakeup_thread(conf->mddev->thread);
                } else {
                        if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -244,6 +251,9 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
        spin_lock_irq(&conf->device_lock);
 
        do {
+               wait_event_lock_irq(conf->wait_for_stripe,
+                                   conf->quiesce == 0,
+                                   conf->device_lock, /* nothing */);
                sh = __find_stripe(conf, sector);
                if (!sh) {
                        if (!conf->inactive_blocked)
@@ -803,6 +813,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 {
        struct bio **bip;
        raid5_conf_t *conf = sh->raid_conf;
+       int firstwrite=0;
 
        PRINTK("adding bh b#%llu to stripe s#%llu\n",
                (unsigned long long)bi->bi_sector,
@@ -811,9 +822,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 
        spin_lock(&sh->lock);
        spin_lock_irq(&conf->device_lock);
-       if (forwrite)
+       if (forwrite) {
                bip = &sh->dev[dd_idx].towrite;
-       else
+               if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+                       firstwrite = 1;
+       } else
                bip = &sh->dev[dd_idx].toread;
        while (*bip && (*bip)->bi_sector < bi->bi_sector) {
                if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -836,6 +849,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                (unsigned long long)bi->bi_sector,
                (unsigned long long)sh->sector, dd_idx);
 
+       if (conf->mddev->bitmap && firstwrite) {
+               sh->bm_seq = conf->seq_write;
+               bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+                                 STRIPE_SECTORS, 0);
+               set_bit(STRIPE_BIT_DELAY, &sh->state);
+       }
+
        if (forwrite) {
                /* check if page is covered */
                sector_t sector = sh->dev[dd_idx].sector;
@@ -958,12 +978,13 @@ static void handle_stripe(struct stripe_head *sh)
         * need to be failed
         */
        if (failed > 1 && to_read+to_write+written) {
-               spin_lock_irq(&conf->device_lock);
                for (i=disks; i--; ) {
+                       int bitmap_end = 0;
+                       spin_lock_irq(&conf->device_lock);
                        /* fail all writes first */
                        bi = sh->dev[i].towrite;
                        sh->dev[i].towrite = NULL;
-                       if (bi) to_write--;
+                       if (bi) { to_write--; bitmap_end = 1; }
 
                        if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
                                wake_up(&conf->wait_for_overlap);
@@ -981,6 +1002,7 @@ static void handle_stripe(struct stripe_head *sh)
                        /* and fail all 'written' */
                        bi = sh->dev[i].written;
                        sh->dev[i].written = NULL;
+                       if (bi) bitmap_end = 1;
                        while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
                                struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
                                clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1009,8 +1031,11 @@ static void handle_stripe(struct stripe_head *sh)
                                        bi = nextbi;
                                }
                        }
+                       spin_unlock_irq(&conf->device_lock);
+                       if (bitmap_end)
+                               bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                               STRIPE_SECTORS, 0, 0);
                }
-               spin_unlock_irq(&conf->device_lock);
        }
        if (failed > 1 && syncing) {
                md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1038,6 +1063,7 @@ static void handle_stripe(struct stripe_head *sh)
                         test_bit(R5_UPTODATE, &dev->flags) ) {
                        /* We can return any write requests */
                            struct bio *wbi, *wbi2;
+                           int bitmap_end = 0;
                            PRINTK("Return write for disc %d\n", i);
                            spin_lock_irq(&conf->device_lock);
                            wbi = dev->written;
@@ -1051,7 +1077,13 @@ static void handle_stripe(struct stripe_head *sh)
                                    }
                                    wbi = wbi2;
                            }
+                           if (dev->towrite == NULL)
+                                   bitmap_end = 1;
                            spin_unlock_irq(&conf->device_lock);
+                           if (bitmap_end)
+                                   bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                                   STRIPE_SECTORS,
+                                                   !test_bit(STRIPE_DEGRADED, &sh->state), 0);
                    }
                }
        }
@@ -1175,7 +1207,8 @@ static void handle_stripe(struct stripe_head *sh)
                                }
                        }
                /* now if nothing is locked, and if we have enough data, we can start a write request */
-               if (locked == 0 && (rcw == 0 ||rmw == 0)) {
+               if (locked == 0 && (rcw == 0 ||rmw == 0) &&
+                   !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
                        PRINTK("Computing parity...\n");
                        compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
                        /* now every locked buffer is ready to be written */
@@ -1231,6 +1264,7 @@ static void handle_stripe(struct stripe_head *sh)
                        dev = &sh->dev[failed_num];
                        set_bit(R5_LOCKED, &dev->flags);
                        set_bit(R5_Wantwrite, &dev->flags);
+                       clear_bit(STRIPE_DEGRADED, &sh->state);
                        locked++;
                        set_bit(STRIPE_INSYNC, &sh->state);
                        set_bit(R5_Syncio, &dev->flags);
@@ -1298,6 +1332,8 @@ static void handle_stripe(struct stripe_head *sh)
                        bi->bi_next = NULL;
                        generic_make_request(bi);
                } else {
+                       if (rw == 1)
+                               set_bit(STRIPE_DEGRADED, &sh->state);
                        PRINTK("skip op %ld on disc %d for sector %llu\n",
                                bi->bi_rw, i, (unsigned long long)sh->sector);
                        clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1322,6 +1358,20 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
        }
 }
 
+static inline void activate_bit_delay(raid5_conf_t *conf)
+{
+       /* device_lock is held */
+       struct list_head head;
+       list_add(&head, &conf->bitmap_list);
+       list_del_init(&conf->bitmap_list);
+       while (!list_empty(&head)) {
+               struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+               list_del_init(&sh->lru);
+               atomic_inc(&sh->count);
+               __release_stripe(conf, sh);
+       }
+}
+
 static void unplug_slaves(mddev_t *mddev)
 {
        raid5_conf_t *conf = mddev_to_conf(mddev);
@@ -1354,8 +1404,10 @@ static void raid5_unplug_device(request_queue_t *q)
 
        spin_lock_irqsave(&conf->device_lock, flags);
 
-       if (blk_remove_plug(q))
+       if (blk_remove_plug(q)) {
+               conf->seq_flush++;
                raid5_activate_delayed(conf);
+       }
        md_wakeup_thread(mddev->thread);
 
        spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1411,6 +1463,11 @@ static int make_request (request_queue_t *q, struct bio * bi)
        sector_t logical_sector, last_sector;
        struct stripe_head *sh;
 
+       if (unlikely(bio_barrier(bi))) {
+               bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        md_write_start(mddev, bi);
 
        if (bio_data_dir(bi)==WRITE) {
@@ -1488,10 +1545,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        sector_t first_sector;
        int raid_disks = conf->raid_disks;
        int data_disks = raid_disks-1;
+       sector_t max_sector = mddev->size << 1;
+       int sync_blocks;
 
-       if (sector_nr >= mddev->size <<1) {
+       if (sector_nr >= max_sector) {
                /* just being told to finish up .. nothing much to do */
                unplug_slaves(mddev);
+
+               if (mddev->curr_resync < max_sector) /* aborted */
+                       bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+                                       &sync_blocks, 1);
+               else /* compelted sync */
+                       conf->fullsync = 0;
+               bitmap_close_sync(mddev->bitmap);
+
                return 0;
        }
        /* if there is 1 or more failed drives and we are trying
@@ -1503,6 +1570,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                *skipped = 1;
                return rv;
        }
+       if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+           !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+               /* we can skip this block, and probably more */
+               sync_blocks /= STRIPE_SECTORS;
+               *skipped = 1;
+               return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+       }
 
        x = sector_nr;
        chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1520,6 +1594,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(1);
        }
+       bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
        spin_lock(&sh->lock);   
        set_bit(STRIPE_SYNCING, &sh->state);
        clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1553,6 +1628,13 @@ static void raid5d (mddev_t *mddev)
        while (1) {
                struct list_head *first;
 
+               if (conf->seq_flush - conf->seq_write > 0) {
+                       int seq = conf->seq_flush;
+                       bitmap_unplug(mddev->bitmap);
+                       conf->seq_write = seq;
+                       activate_bit_delay(conf);
+               }
+
                if (list_empty(&conf->handle_list) &&
                    atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
                    !blk_queue_plugged(mddev->queue) &&
@@ -1586,7 +1668,7 @@ static void raid5d (mddev_t *mddev)
        PRINTK("--- raid5d inactive\n");
 }
 
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
 {
        raid5_conf_t *conf;
        int raid_disk, memory;
@@ -1616,6 +1698,7 @@ static int run (mddev_t *mddev)
        init_waitqueue_head(&conf->wait_for_overlap);
        INIT_LIST_HEAD(&conf->handle_list);
        INIT_LIST_HEAD(&conf->delayed_list);
+       INIT_LIST_HEAD(&conf->bitmap_list);
        INIT_LIST_HEAD(&conf->inactive_list);
        atomic_set(&conf->active_stripes, 0);
        atomic_set(&conf->preread_active_stripes, 0);
@@ -1727,6 +1810,9 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
 
        /* Ok, everything is just fine now */
 
+       if (mddev->bitmap)
+               mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
        mddev->queue->unplug_fn = raid5_unplug_device;
        mddev->queue->issue_flush_fn = raid5_issue_flush;
 
@@ -1907,6 +1993,8 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                        rdev->in_sync = 0;
                        rdev->raid_disk = disk;
                        found = 1;
+                       if (rdev->saved_raid_disk != disk)
+                               conf->fullsync = 1;
                        p->rdev = rdev;
                        break;
                }
@@ -1936,6 +2024,35 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
        return 0;
 }
 
+static void raid5_quiesce(mddev_t *mddev, int state)
+{
+       raid5_conf_t *conf = mddev_to_conf(mddev);
+
+       switch(state) {
+       case 1: /* stop all writes */
+               spin_lock_irq(&conf->device_lock);
+               conf->quiesce = 1;
+               wait_event_lock_irq(conf->wait_for_stripe,
+                                   atomic_read(&conf->active_stripes) == 0,
+                                   conf->device_lock, /* nothing */);
+               spin_unlock_irq(&conf->device_lock);
+               break;
+
+       case 0: /* re-enable writes */
+               spin_lock_irq(&conf->device_lock);
+               conf->quiesce = 0;
+               wake_up(&conf->wait_for_stripe);
+               spin_unlock_irq(&conf->device_lock);
+               break;
+       }
+       if (mddev->thread) {
+               if (mddev->bitmap)
+                       mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+               else
+                       mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+               md_wakeup_thread(mddev->thread);
+       }
+}
 static mdk_personality_t raid5_personality=
 {
        .name           = "raid5",
@@ -1950,6 +2067,7 @@ static mdk_personality_t raid5_personality=
        .spare_active   = raid5_spare_active,
        .sync_request   = sync_request,
        .resize         = raid5_resize,
+       .quiesce        = raid5_quiesce,
 };
 
 static int __init raid5_init (void)
index 495dee1d1e8335bcef634be427e0132bb596413e..267eb1430c834094318f728d81c912ac03d1f37c 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/atomic.h>
 #include "raid6.h"
 
+#include <linux/raid/bitmap.h>
+
 /*
  * Stripe cache
  */
@@ -98,8 +100,13 @@ static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
                if (test_bit(STRIPE_HANDLE, &sh->state)) {
                        if (test_bit(STRIPE_DELAYED, &sh->state))
                                list_add_tail(&sh->lru, &conf->delayed_list);
-                       else
+                       else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+                                conf->seq_write == sh->bm_seq)
+                               list_add_tail(&sh->lru, &conf->bitmap_list);
+                       else {
+                               clear_bit(STRIPE_BIT_DELAY, &sh->state);
                                list_add_tail(&sh->lru, &conf->handle_list);
+                       }
                        md_wakeup_thread(conf->mddev->thread);
                } else {
                        if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -262,6 +269,9 @@ static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector
        spin_lock_irq(&conf->device_lock);
 
        do {
+               wait_event_lock_irq(conf->wait_for_stripe,
+                                   conf->quiesce == 0,
+                                   conf->device_lock, /* nothing */);
                sh = __find_stripe(conf, sector);
                if (!sh) {
                        if (!conf->inactive_blocked)
@@ -906,6 +916,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 {
        struct bio **bip;
        raid6_conf_t *conf = sh->raid_conf;
+       int firstwrite=0;
 
        PRINTK("adding bh b#%llu to stripe s#%llu\n",
                (unsigned long long)bi->bi_sector,
@@ -914,9 +925,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 
        spin_lock(&sh->lock);
        spin_lock_irq(&conf->device_lock);
-       if (forwrite)
+       if (forwrite) {
                bip = &sh->dev[dd_idx].towrite;
-       else
+               if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+                       firstwrite = 1;
+       } else
                bip = &sh->dev[dd_idx].toread;
        while (*bip && (*bip)->bi_sector < bi->bi_sector) {
                if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -939,6 +952,13 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
                (unsigned long long)bi->bi_sector,
                (unsigned long long)sh->sector, dd_idx);
 
+       if (conf->mddev->bitmap && firstwrite) {
+               sh->bm_seq = conf->seq_write;
+               bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+                                 STRIPE_SECTORS, 0);
+               set_bit(STRIPE_BIT_DELAY, &sh->state);
+       }
+
        if (forwrite) {
                /* check if page is covered */
                sector_t sector = sh->dev[dd_idx].sector;
@@ -1066,12 +1086,13 @@ static void handle_stripe(struct stripe_head *sh)
         * need to be failed
         */
        if (failed > 2 && to_read+to_write+written) {
-               spin_lock_irq(&conf->device_lock);
                for (i=disks; i--; ) {
+                       int bitmap_end = 0;
+                       spin_lock_irq(&conf->device_lock);
                        /* fail all writes first */
                        bi = sh->dev[i].towrite;
                        sh->dev[i].towrite = NULL;
-                       if (bi) to_write--;
+                       if (bi) { to_write--; bitmap_end = 1; }
 
                        if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
                                wake_up(&conf->wait_for_overlap);
@@ -1089,6 +1110,7 @@ static void handle_stripe(struct stripe_head *sh)
                        /* and fail all 'written' */
                        bi = sh->dev[i].written;
                        sh->dev[i].written = NULL;
+                       if (bi) bitmap_end = 1;
                        while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
                                struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
                                clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1117,8 +1139,11 @@ static void handle_stripe(struct stripe_head *sh)
                                        bi = nextbi;
                                }
                        }
+                       spin_unlock_irq(&conf->device_lock);
+                       if (bitmap_end)
+                               bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                               STRIPE_SECTORS, 0, 0);
                }
-               spin_unlock_irq(&conf->device_lock);
        }
        if (failed > 2 && syncing) {
                md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1155,6 +1180,7 @@ static void handle_stripe(struct stripe_head *sh)
                                if (!test_bit(R5_LOCKED, &dev->flags) &&
                                    test_bit(R5_UPTODATE, &dev->flags) ) {
                                        /* We can return any write requests */
+                                       int bitmap_end = 0;
                                        struct bio *wbi, *wbi2;
                                        PRINTK("Return write for stripe %llu disc %d\n",
                                               (unsigned long long)sh->sector, i);
@@ -1170,7 +1196,13 @@ static void handle_stripe(struct stripe_head *sh)
                                                }
                                                wbi = wbi2;
                                        }
+                                       if (dev->towrite == NULL)
+                                               bitmap_end = 1;
                                        spin_unlock_irq(&conf->device_lock);
+                                       if (bitmap_end)
+                                               bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+                                                               STRIPE_SECTORS,
+                                                               !test_bit(STRIPE_DEGRADED, &sh->state), 0);
                                }
                        }
        }
@@ -1285,7 +1317,8 @@ static void handle_stripe(struct stripe_head *sh)
                                }
                        }
                /* now if nothing is locked, and if we have enough data, we can start a write request */
-               if (locked == 0 && rcw == 0) {
+               if (locked == 0 && rcw == 0 &&
+                   !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
                        if ( must_compute > 0 ) {
                                /* We have failed blocks and need to compute them */
                                switch ( failed ) {
@@ -1388,6 +1421,7 @@ static void handle_stripe(struct stripe_head *sh)
                        bdev = &sh->dev[failed_num[1]];
                        locked += !test_bit(R5_LOCKED, &bdev->flags);
                        set_bit(R5_LOCKED, &bdev->flags);
+                       clear_bit(STRIPE_DEGRADED, &sh->state);
                        set_bit(R5_Wantwrite, &bdev->flags);
 
                        set_bit(STRIPE_INSYNC, &sh->state);
@@ -1457,6 +1491,8 @@ static void handle_stripe(struct stripe_head *sh)
                        bi->bi_next = NULL;
                        generic_make_request(bi);
                } else {
+                       if (rw == 1)
+                               set_bit(STRIPE_DEGRADED, &sh->state);
                        PRINTK("skip op %ld on disc %d for sector %llu\n",
                                bi->bi_rw, i, (unsigned long long)sh->sector);
                        clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1481,6 +1517,20 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
        }
 }
 
+static inline void activate_bit_delay(raid6_conf_t *conf)
+{
+       /* device_lock is held */
+       struct list_head head;
+       list_add(&head, &conf->bitmap_list);
+       list_del_init(&conf->bitmap_list);
+       while (!list_empty(&head)) {
+               struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+               list_del_init(&sh->lru);
+               atomic_inc(&sh->count);
+               __release_stripe(conf, sh);
+       }
+}
+
 static void unplug_slaves(mddev_t *mddev)
 {
        raid6_conf_t *conf = mddev_to_conf(mddev);
@@ -1513,8 +1563,10 @@ static void raid6_unplug_device(request_queue_t *q)
 
        spin_lock_irqsave(&conf->device_lock, flags);
 
-       if (blk_remove_plug(q))
+       if (blk_remove_plug(q)) {
+               conf->seq_flush++;
                raid6_activate_delayed(conf);
+       }
        md_wakeup_thread(mddev->thread);
 
        spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1570,6 +1622,11 @@ static int make_request (request_queue_t *q, struct bio * bi)
        sector_t logical_sector, last_sector;
        struct stripe_head *sh;
 
+       if (unlikely(bio_barrier(bi))) {
+               bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        md_write_start(mddev, bi);
 
        if (bio_data_dir(bi)==WRITE) {
@@ -1647,10 +1704,20 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        sector_t first_sector;
        int raid_disks = conf->raid_disks;
        int data_disks = raid_disks - 2;
+       sector_t max_sector = mddev->size << 1;
+       int sync_blocks;
 
-       if (sector_nr >= mddev->size <<1) {
+       if (sector_nr >= max_sector) {
                /* just being told to finish up .. nothing much to do */
                unplug_slaves(mddev);
+
+               if (mddev->curr_resync < max_sector) /* aborted */
+                       bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+                                       &sync_blocks, 1);
+               else /* compelted sync */
+                       conf->fullsync = 0;
+               bitmap_close_sync(mddev->bitmap);
+
                return 0;
        }
        /* if there are 2 or more failed drives and we are trying
@@ -1662,6 +1729,13 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                *skipped = 1;
                return rv;
        }
+       if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+           !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+               /* we can skip this block, and probably more */
+               sync_blocks /= STRIPE_SECTORS;
+               *skipped = 1;
+               return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+       }
 
        x = sector_nr;
        chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1679,6 +1753,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(1);
        }
+       bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
        spin_lock(&sh->lock);
        set_bit(STRIPE_SYNCING, &sh->state);
        clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1712,6 +1787,13 @@ static void raid6d (mddev_t *mddev)
        while (1) {
                struct list_head *first;
 
+               if (conf->seq_flush - conf->seq_write > 0) {
+                       int seq = conf->seq_flush;
+                       bitmap_unplug(mddev->bitmap);
+                       conf->seq_write = seq;
+                       activate_bit_delay(conf);
+               }
+
                if (list_empty(&conf->handle_list) &&
                    atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
                    !blk_queue_plugged(mddev->queue) &&
@@ -1745,7 +1827,7 @@ static void raid6d (mddev_t *mddev)
        PRINTK("--- raid6d inactive\n");
 }
 
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
 {
        raid6_conf_t *conf;
        int raid_disk, memory;
@@ -1775,6 +1857,7 @@ static int run (mddev_t *mddev)
        init_waitqueue_head(&conf->wait_for_overlap);
        INIT_LIST_HEAD(&conf->handle_list);
        INIT_LIST_HEAD(&conf->delayed_list);
+       INIT_LIST_HEAD(&conf->bitmap_list);
        INIT_LIST_HEAD(&conf->inactive_list);
        atomic_set(&conf->active_stripes, 0);
        atomic_set(&conf->preread_active_stripes, 0);
@@ -1894,6 +1977,9 @@ static int run (mddev_t *mddev)
        /* Ok, everything is just fine now */
        mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
 
+       if (mddev->bitmap)
+               mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
        mddev->queue->unplug_fn = raid6_unplug_device;
        mddev->queue->issue_flush_fn = raid6_issue_flush;
        return 0;
@@ -2071,6 +2157,8 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                        rdev->in_sync = 0;
                        rdev->raid_disk = disk;
                        found = 1;
+                       if (rdev->saved_raid_disk != disk)
+                               conf->fullsync = 1;
                        p->rdev = rdev;
                        break;
                }
@@ -2100,6 +2188,35 @@ static int raid6_resize(mddev_t *mddev, sector_t sectors)
        return 0;
 }
 
+static void raid6_quiesce(mddev_t *mddev, int state)
+{
+       raid6_conf_t *conf = mddev_to_conf(mddev);
+
+       switch(state) {
+       case 1: /* stop all writes */
+               spin_lock_irq(&conf->device_lock);
+               conf->quiesce = 1;
+               wait_event_lock_irq(conf->wait_for_stripe,
+                                   atomic_read(&conf->active_stripes) == 0,
+                                   conf->device_lock, /* nothing */);
+               spin_unlock_irq(&conf->device_lock);
+               break;
+
+       case 0: /* re-enable writes */
+               spin_lock_irq(&conf->device_lock);
+               conf->quiesce = 0;
+               wake_up(&conf->wait_for_stripe);
+               spin_unlock_irq(&conf->device_lock);
+               break;
+       }
+       if (mddev->thread) {
+               if (mddev->bitmap)
+                       mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+               else
+                       mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+               md_wakeup_thread(mddev->thread);
+       }
+}
 static mdk_personality_t raid6_personality=
 {
        .name           = "raid6",
@@ -2114,6 +2231,7 @@ static mdk_personality_t raid6_personality=
        .spare_active   = raid6_spare_active,
        .sync_request   = sync_request,
        .resize         = raid6_resize,
+       .quiesce        = raid6_quiesce,
 };
 
 static int __init raid6_init (void)
index 772d6112fb3b65ea451d69ed269f57864f78319d..c578a529e7a8e910ea969b3fad2c58b28d95ca2d 100644 (file)
@@ -2,4 +2,7 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := video/ radio/ dvb/ common/
+obj-y := common/
+obj-$(CONFIG_VIDEO_DEV) += video/
+obj-$(CONFIG_VIDEO_DEV) += radio/
+obj-$(CONFIG_DVB)       += dvb/
index ab7a1fba4427c511fe34a89f724205700ce5e409..a0e700d7a4a4ad5b5fb6c3ff7b052ff1b0449791 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: ir-common.c,v 1.11 2005/07/07 14:44:43 mchehab Exp $
  *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
@@ -335,6 +334,72 @@ int ir_dump_samples(u32 *samples, int count)
        return 0;
 }
 
+/* decode raw samples, pulse distance coding used by NEC remotes */
+int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
+{
+       int i,last,bit,len;
+       u32 curBit;
+       u32 value;
+
+       /* find start burst */
+       for (i = len = 0; i < count * 32; i++) {
+               bit = getbit(samples,i);
+               if (bit) {
+                       len++;
+               } else {
+                       if (len >= 29)
+                               break;
+                       len = 0;
+               }
+       }
+
+       /* start burst to short */
+       if (len < 29)
+               return 0xffffffff;
+
+       /* find start silence */
+       for (len = 0; i < count * 32; i++) {
+               bit = getbit(samples,i);
+               if (bit) {
+                       break;
+               } else {
+                       len++;
+               }
+       }
+
+       /* silence to short */
+       if (len < 7)
+               return 0xffffffff;
+
+       /* go decoding */
+       len   = 0;
+       last = 1;
+       value = 0; curBit = 1;
+       for (; i < count * 32; i++) {
+               bit  = getbit(samples,i);
+               if (last) {
+                       if(bit) {
+                               continue;
+                       } else {
+                               len = 1;
+                       }
+               } else {
+                       if (bit) {
+                               if (len > (low + high) /2)
+                                       value |= curBit;
+                               curBit <<= 1;
+                               if (curBit == 1)
+                                       break;
+                       } else {
+                               len++;
+                       }
+               }
+               last = bit;
+       }
+
+       return value;
+}
+
 /* decode raw samples, biphase coding, used by rc5 for example */
 int ir_decode_biphase(u32 *samples, int count, int low, int high)
 {
@@ -383,6 +448,7 @@ EXPORT_SYMBOL_GPL(ir_input_keydown);
 EXPORT_SYMBOL_GPL(ir_extract_bits);
 EXPORT_SYMBOL_GPL(ir_dump_samples);
 EXPORT_SYMBOL_GPL(ir_decode_biphase);
+EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
 
 /*
  * Local variables:
index cd5828b5e9e346ad2199ef18d542f31ebc0413ec..206cc2f61f26154bb3f5e1a6b62e888ee74e8065 100644 (file)
@@ -168,10 +168,8 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
                return;
        pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
        pt->cpu = NULL;
-       if (NULL != pt->slist) {
-               kfree(pt->slist);
-               pt->slist = NULL;
-       }
+       kfree(pt->slist);
+       pt->slist = NULL;
 }
 
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
index c04fd11526e08432cc648403ecbdaef0e3aeeeb2..37888989ea2e36e75b55a9fa22b09947453eee03 100644 (file)
@@ -1,5 +1,4 @@
 #include <media/saa7146_vv.h>
-#include <linux/version.h>
 
 #define BOARD_CAN_DO_VBI(dev)   (dev->revision != 0 && dev->vv_data->vbi_minor != -1) 
 
index 6284894505c6f0595d8afb06e06087c1b8231cbe..fec6beab8c2873d95715f67a38b4d20bc97d04c9 100644 (file)
@@ -1,4 +1,3 @@
-#include <linux/version.h>
 #include <media/saa7146_vv.h>
 
 static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
@@ -402,12 +401,9 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
        saa7146_i2c_reset(dev);
 
        if( NULL != i2c_adapter ) {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-               i2c_adapter->data = dev;
-#else
                BUG_ON(!i2c_adapter->class);
                i2c_set_adapdata(i2c_adapter,dev);
-#endif
+               i2c_adapter->dev.parent    = &dev->pci->dev;
                i2c_adapter->algo          = &saa7146_algo;
                i2c_adapter->algo_data     = NULL;
                i2c_adapter->id            = I2C_HW_SAA7146;
index 0410cc96a48e2cc3a90238ab92e4dd45904d4e2f..47e28b0ee951bcee5debf4a0b8f1c56879acd6c3 100644 (file)
@@ -164,12 +164,11 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
        return 0;
 }
 
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
 {
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       struct flexcop_device *fc = fe->dvb->priv;
 
        div = params->frequency / 125;
 
@@ -180,7 +179,7 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 
        if (params->frequency < 1500000) buf[3] |= 0x10;
 
-       if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(i2c, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -335,8 +334,103 @@ static struct mt312_config skystar23_samsung_tbdu18132_config = {
        .pll_set = skystar23_samsung_tbdu18132_pll_set,
 };
 
+
+static u8 alps_tdee4_stv0297_inittab[] = {
+       0x80, 0x01,
+       0x80, 0x00,
+       0x81, 0x01,
+       0x81, 0x00,
+       0x00, 0x09,
+       0x01, 0x69,
+       0x03, 0x00,
+       0x04, 0x00,
+       0x07, 0x00,
+       0x08, 0x00,
+       0x20, 0x00,
+       0x21, 0x40,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x24, 0x40,
+       0x25, 0x88,
+       0x30, 0xff,
+       0x31, 0x00,
+       0x32, 0xff,
+       0x33, 0x00,
+       0x34, 0x50,
+       0x35, 0x7f,
+       0x36, 0x00,
+       0x37, 0x20,
+       0x38, 0x00,
+       0x40, 0x1c,
+       0x41, 0xff,
+       0x42, 0x29,
+       0x43, 0x00,
+       0x44, 0xff,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x49, 0x04,
+       0x4a, 0x00,
+       0x4b, 0xf8,
+       0x52, 0x30,
+       0x55, 0xae,
+       0x56, 0x47,
+       0x57, 0xe1,
+       0x58, 0x3a,
+       0x5a, 0x1e,
+       0x5b, 0x34,
+       0x60, 0x00,
+       0x63, 0x00,
+       0x64, 0x00,
+       0x65, 0x00,
+       0x66, 0x00,
+       0x67, 0x00,
+       0x68, 0x00,
+       0x69, 0x00,
+       0x6a, 0x02,
+       0x6b, 0x00,
+       0x70, 0xff,
+       0x71, 0x00,
+       0x72, 0x00,
+       0x73, 0x00,
+       0x74, 0x0c,
+       0x80, 0x00,
+       0x81, 0x00,
+       0x82, 0x00,
+       0x83, 0x00,
+       0x84, 0x04,
+       0x85, 0x80,
+       0x86, 0x24,
+       0x87, 0x78,
+       0x88, 0x10,
+       0x89, 0x00,
+       0x90, 0x01,
+       0x91, 0x01,
+       0xa0, 0x04,
+       0xa1, 0x00,
+       0xa2, 0x00,
+       0xb0, 0x91,
+       0xb1, 0x0b,
+       0xc0, 0x53,
+       0xc1, 0x70,
+       0xc2, 0x12,
+       0xd0, 0x00,
+       0xd1, 0x00,
+       0xd2, 0x00,
+       0xd3, 0x00,
+       0xd4, 0x00,
+       0xd5, 0x00,
+       0xde, 0x00,
+       0xdf, 0x00,
+       0x61, 0x49,
+       0x62, 0x0b,
+       0x53, 0x08,
+       0x59, 0x08,
+       0xff, 0xff,
+};
+
 static struct stv0297_config alps_tdee4_stv0297_config = {
        .demod_address = 0x1c,
+       .inittab = alps_tdee4_stv0297_inittab,
 //     .invert = 1,
 //     .pll_set = alps_tdee4_stv0297_pll_set,
 };
@@ -370,7 +464,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
                info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
        } else
        /* try the cable dvb (stv0297) */
-       if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
+       if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type                        = FC_CABLE;
                info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
        } else
index 3c5a8e273c4aa47488837a3110deab42f33099b2..f29571450038b4f996799fc7ad4757e1f8d90ad1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
  *
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
  *
  * large parts based on the bttv driver
  * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@metzlerbros.de)
@@ -219,7 +219,7 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
        controlreg &= ~0x1f;
        controlreg |= 0x1b;
 
-       btwrite(cpu_to_le32(bt->risc_dma), BT878_ARISC_START);
+       btwrite(bt->risc_dma, BT878_ARISC_START);
 
        /* original int mask had :
         *    6    2    8    4    0
index 837623f7fcdfce60e08bc97de33c09134c49462f..a73baf00ca3907206a40725cdd8fd674a5f3b6d9 100644 (file)
@@ -1,7 +1,7 @@
 /*
     bt878.h - Bt878 audio module (register offsets)
 
-    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
index 07a0b0a968a62e893ddea38733c5ed783861615c..34a837a1abf4f1d5beeef0dd0dec301eba984d87 100644 (file)
@@ -1,5 +1,4 @@
 /*
-
        Frontend/Card driver for TwinHan DST Frontend
        Copyright (C) 2003 Jamie Honan
        Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
@@ -19,7 +18,6 @@
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <asm/div64.h>
-
 #include "dvb_frontend.h"
 #include "dst_priv.h"
 #include "dst_common.h"
 
-
 static unsigned int verbose = 1;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
 
-static unsigned int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug messages, default is 0 (yes)");
-
 static unsigned int dst_addons;
 module_param(dst_addons, int, 0644);
 MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 
-#define dprintk        if (debug) printk
-
-#define HAS_LOCK       1
-#define ATTEMPT_TUNE   2
-#define HAS_POWER      4
-
-static void dst_packsize(struct dst_state* state, int psize)
+#define HAS_LOCK               1
+#define ATTEMPT_TUNE           2
+#define HAS_POWER              4
+
+#define DST_ERROR              0
+#define DST_NOTICE             1
+#define DST_INFO               2
+#define DST_DEBUG              3
+
+#define dprintk(x, y, z, format, arg...) do {                                          \
+       if (z) {                                                                        \
+               if      ((x > DST_ERROR) && (x > y))                                    \
+                       printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);      \
+               else if ((x > DST_NOTICE) && (x > y))                                   \
+                       printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);   \
+               else if ((x > DST_INFO) && (x > y))                                     \
+                       printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);     \
+               else if ((x > DST_DEBUG) && (x > y))                                    \
+                       printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);    \
+       } else {                                                                        \
+               if (x > y)                                                              \
+                       printk(format, ##arg);                                          \
+       }                                                                               \
+} while(0)
+
+
+static void dst_packsize(struct dst_state *state, int psize)
 {
        union dst_gpio_packet bits;
 
@@ -60,7 +72,7 @@ static void dst_packsize(struct dst_state* state, int psize)
        bt878_device_control(state->bt, DST_IG_TS, &bits);
 }
 
-int dst_gpio_outb(struct dst_statestate, u32 mask, u32 enbb, u32 outhigh, int delay)
+int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int delay)
 {
        union dst_gpio_packet enb;
        union dst_gpio_packet bits;
@@ -68,63 +80,55 @@ int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int
 
        enb.enb.mask = mask;
        enb.enb.enable = enbb;
-       if (verbose > 4)
-               dprintk("%s: mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", __FUNCTION__, mask, enbb, outhigh);
 
+       dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
        if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
-               dprintk("%s: dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", __FUNCTION__, err, mask, enbb);
+               dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
                return -EREMOTEIO;
        }
        udelay(1000);
        /* because complete disabling means no output, no need to do output packet */
        if (enbb == 0)
                return 0;
-
        if (delay)
                msleep(10);
-
        bits.outp.mask = enbb;
        bits.outp.highvals = outhigh;
-
        if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
-               dprintk("%s: dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", __FUNCTION__, err, enbb, outhigh);
+               dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
                return -EREMOTEIO;
        }
+
        return 0;
 }
 EXPORT_SYMBOL(dst_gpio_outb);
 
-int dst_gpio_inb(struct dst_state *state, u8 * result)
+int dst_gpio_inb(struct dst_state *state, u8 *result)
 {
        union dst_gpio_packet rd_packet;
        int err;
 
        *result = 0;
-
        if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
-               dprintk("%s: dst_gpio_inb error (err == %i)\n", __FUNCTION__, err);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
                return -EREMOTEIO;
        }
-
        *result = (u8) rd_packet.rd.value;
+
        return 0;
 }
 EXPORT_SYMBOL(dst_gpio_inb);
 
 int rdc_reset_state(struct dst_state *state)
 {
-       if (verbose > 1)
-               dprintk("%s: Resetting state machine\n", __FUNCTION__);
-
+       dprintk(verbose, DST_INFO, 1, "Resetting state machine");
        if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
-               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
                return -1;
        }
-
        msleep(10);
-
        if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
-               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
                msleep(10);
                return -1;
        }
@@ -135,16 +139,14 @@ EXPORT_SYMBOL(rdc_reset_state);
 
 int rdc_8820_reset(struct dst_state *state)
 {
-       if (verbose > 1)
-               dprintk("%s: Resetting DST\n", __FUNCTION__);
-
+       dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
        if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
-               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
                return -1;
        }
        udelay(1000);
        if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
-               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
                return -1;
        }
 
@@ -155,10 +157,11 @@ EXPORT_SYMBOL(rdc_8820_reset);
 int dst_pio_enable(struct dst_state *state)
 {
        if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
-               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
                return -1;
        }
        udelay(1000);
+
        return 0;
 }
 EXPORT_SYMBOL(dst_pio_enable);
@@ -166,7 +169,7 @@ EXPORT_SYMBOL(dst_pio_enable);
 int dst_pio_disable(struct dst_state *state)
 {
        if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
-               dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
                return -1;
        }
        if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -183,19 +186,16 @@ int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
 
        for (i = 0; i < 200; i++) {
                if (dst_gpio_inb(state, &reply) < 0) {
-                       dprintk("%s: dst_gpio_inb ERROR !\n", __FUNCTION__);
+                       dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
                        return -1;
                }
-
                if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
-                       if (verbose > 4)
-                               dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i);
+                       dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
                        return 1;
                }
                msleep(10);
        }
-       if (verbose > 1)
-               dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+       dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
 
        return 0;
 }
@@ -203,7 +203,7 @@ EXPORT_SYMBOL(dst_wait_dst_ready);
 
 int dst_error_recovery(struct dst_state *state)
 {
-       dprintk("%s: Trying to return from previous errors...\n", __FUNCTION__);
+       dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
        dst_pio_disable(state);
        msleep(10);
        dst_pio_enable(state);
@@ -215,7 +215,7 @@ EXPORT_SYMBOL(dst_error_recovery);
 
 int dst_error_bailout(struct dst_state *state)
 {
-       dprintk("%s: Trying to bailout from previous error...\n", __FUNCTION__);
+       dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
        rdc_8820_reset(state);
        dst_pio_disable(state);
        msleep(10);
@@ -224,17 +224,15 @@ int dst_error_bailout(struct dst_state *state)
 }
 EXPORT_SYMBOL(dst_error_bailout);
 
-
-int dst_comm_init(struct dst_state* state)
+int dst_comm_init(struct dst_state *state)
 {
-       if (verbose > 1)
-               dprintk ("%s: Initializing DST..\n", __FUNCTION__);
+       dprintk(verbose, DST_INFO, 1, "Initializing DST.");
        if ((dst_pio_enable(state)) < 0) {
-               dprintk("%s: PIO Enable Failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
                return -1;
        }
        if ((rdc_reset_state(state)) < 0) {
-               dprintk("%s: RDC 8820 State RESET Failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
                return -1;
        }
        if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -246,36 +244,33 @@ int dst_comm_init(struct dst_state* state)
 }
 EXPORT_SYMBOL(dst_comm_init);
 
-
 int write_dst(struct dst_state *state, u8 *data, u8 len)
 {
        struct i2c_msg msg = {
-               .addr = state->config->demod_address,.flags = 0,.buf = data,.len = len
+               .addr = state->config->demod_address,
+               .flags = 0,
+               .buf = data,
+               .len = len
        };
 
        int err;
-       int cnt;
-       if (debug && (verbose > 4)) {
-               u8 i;
-               if (verbose > 4) {
-                       dprintk("%s writing [ ", __FUNCTION__);
-                       for (i = 0; i < len; i++)
-                               dprintk("%02x ", data[i]);
-                       dprintk("]\n");
-               }
-       }
+       u8 cnt, i;
+
+       dprintk(verbose, DST_NOTICE, 0, "writing [ ");
+       for (i = 0; i < len; i++)
+               dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
+       dprintk(verbose, DST_NOTICE, 0, "]\n");
+
        for (cnt = 0; cnt < 2; cnt++) {
                if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-                       dprintk("%s: _write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
+                       dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
                        dst_error_recovery(state);
                        continue;
                } else
                        break;
        }
-
        if (cnt >= 2) {
-               if (verbose > 1)
-                       printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+               dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
                dst_error_bailout(state);
 
                return -1;
@@ -285,36 +280,37 @@ int write_dst(struct dst_state *state, u8 *data, u8 len)
 }
 EXPORT_SYMBOL(write_dst);
 
-int read_dst(struct dst_state *state, u8 * ret, u8 len)
+int read_dst(struct dst_state *state, u8 *ret, u8 len)
 {
-       struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len };
+       struct i2c_msg msg = {
+               .addr = state->config->demod_address,
+               .flags = I2C_M_RD,
+               .buf = ret,
+               .len = len
+       };
+
        int err;
        int cnt;
 
        for (cnt = 0; cnt < 2; cnt++) {
                if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-
-                       dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
+                       dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
                        dst_error_recovery(state);
-
                        continue;
                } else
                        break;
        }
        if (cnt >= 2) {
-               if (verbose > 1)
-                       printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+               dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
                dst_error_bailout(state);
 
                return -1;
        }
-       if (debug && (verbose > 4)) {
-               dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
-               for (err = 1; err < len; err++)
-                       dprintk(" 0x%x", ret[err]);
-               if (err > 1)
-                       dprintk("\n");
-       }
+       dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
+       for (err = 1; err < len; err++)
+               dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
+       if (err > 1)
+               dprintk(verbose, DST_DEBUG, 0, "\n");
 
        return 0;
 }
@@ -323,19 +319,16 @@ EXPORT_SYMBOL(read_dst);
 static int dst_set_polarization(struct dst_state *state)
 {
        switch (state->voltage) {
-               case SEC_VOLTAGE_13:    // vertical
-                       printk("%s: Polarization=[Vertical]\n", __FUNCTION__);
-                       state->tx_tuna[8] &= ~0x40;  //1
-                       break;
-
-               case SEC_VOLTAGE_18:    // horizontal
-                       printk("%s: Polarization=[Horizontal]\n", __FUNCTION__);
-                       state->tx_tuna[8] |= 0x40;  // 0
-                       break;
-
-               case SEC_VOLTAGE_OFF:
-
-                       break;
+       case SEC_VOLTAGE_13:    /*      Vertical        */
+               dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
+               state->tx_tuna[8] &= ~0x40;
+               break;
+       case SEC_VOLTAGE_18:    /*      Horizontal      */
+               dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
+               state->tx_tuna[8] |= 0x40;
+               break;
+       case SEC_VOLTAGE_OFF:
+               break;
        }
 
        return 0;
@@ -344,14 +337,12 @@ static int dst_set_polarization(struct dst_state *state)
 static int dst_set_freq(struct dst_state *state, u32 freq)
 {
        state->frequency = freq;
-       if (debug > 4)
-               dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
+       dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
 
        if (state->dst_type == DST_TYPE_IS_SAT) {
                freq = freq / 1000;
                if (freq < 950 || freq > 2150)
                        return -EINVAL;
-
                state->tx_tuna[2] = (freq >> 8);
                state->tx_tuna[3] = (u8) freq;
                state->tx_tuna[4] = 0x01;
@@ -360,27 +351,25 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
                        if (freq < 1531)
                                state->tx_tuna[8] |= 0x04;
                }
-
        } else if (state->dst_type == DST_TYPE_IS_TERR) {
                freq = freq / 1000;
                if (freq < 137000 || freq > 858000)
                        return -EINVAL;
-
                state->tx_tuna[2] = (freq >> 16) & 0xff;
                state->tx_tuna[3] = (freq >> 8) & 0xff;
                state->tx_tuna[4] = (u8) freq;
-
        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
+               freq = freq / 1000;
                state->tx_tuna[2] = (freq >> 16) & 0xff;
                state->tx_tuna[3] = (freq >> 8) & 0xff;
                state->tx_tuna[4] = (u8) freq;
-
        } else
                return -EINVAL;
+
        return 0;
 }
 
-static int dst_set_bandwidth(struct dst_statestate, fe_bandwidth_t bandwidth)
+static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth)
 {
        state->bandwidth = bandwidth;
 
@@ -388,103 +377,95 @@ static int dst_set_bandwidth(struct dst_state* state, fe_bandwidth_t bandwidth)
                return 0;
 
        switch (bandwidth) {
-               case BANDWIDTH_6_MHZ:
-                       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-                               state->tx_tuna[7] = 0x06;
-                       else {
-                               state->tx_tuna[6] = 0x06;
-                               state->tx_tuna[7] = 0x00;
-                       }
-                       break;
-
-               case BANDWIDTH_7_MHZ:
-                       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-                               state->tx_tuna[7] = 0x07;
-                       else {
-                               state->tx_tuna[6] = 0x07;
-                               state->tx_tuna[7] = 0x00;
-                       }
-                       break;
-
-               case BANDWIDTH_8_MHZ:
-                       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-                               state->tx_tuna[7] = 0x08;
-                       else {
-                               state->tx_tuna[6] = 0x08;
-                               state->tx_tuna[7] = 0x00;
-                       }
-                       break;
-
-               default:
-                       return -EINVAL;
+       case BANDWIDTH_6_MHZ:
+               if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+                       state->tx_tuna[7] = 0x06;
+               else {
+                       state->tx_tuna[6] = 0x06;
+                       state->tx_tuna[7] = 0x00;
+               }
+               break;
+       case BANDWIDTH_7_MHZ:
+               if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+                       state->tx_tuna[7] = 0x07;
+               else {
+                       state->tx_tuna[6] = 0x07;
+                       state->tx_tuna[7] = 0x00;
+               }
+               break;
+       case BANDWIDTH_8_MHZ:
+               if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+                       state->tx_tuna[7] = 0x08;
+               else {
+                       state->tx_tuna[6] = 0x08;
+                       state->tx_tuna[7] = 0x00;
+               }
+               break;
+       default:
+               return -EINVAL;
        }
+
        return 0;
 }
 
-static int dst_set_inversion(struct dst_statestate, fe_spectral_inversion_t inversion)
+static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion)
 {
        state->inversion = inversion;
        switch (inversion) {
-               case INVERSION_OFF:     // Inversion = Normal
-                       state->tx_tuna[8] &= ~0x80;
-                       break;
-
-               case INVERSION_ON:
-                       state->tx_tuna[8] |= 0x80;
-                       break;
-               default:
-                       return -EINVAL;
+       case INVERSION_OFF:     /*      Inversion = Normal      */
+               state->tx_tuna[8] &= ~0x80;
+               break;
+       case INVERSION_ON:
+               state->tx_tuna[8] |= 0x80;
+               break;
+       default:
+               return -EINVAL;
        }
+
        return 0;
 }
 
-static int dst_set_fec(struct dst_statestate, fe_code_rate_t fec)
+static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
 {
        state->fec = fec;
        return 0;
 }
 
-static fe_code_rate_t dst_get_fec(struct dst_statestate)
+static fe_code_rate_t dst_get_fec(struct dst_state *state)
 {
        return state->fec;
 }
 
-static int dst_set_symbolrate(struct dst_statestate, u32 srate)
+static int dst_set_symbolrate(struct dst_state *state, u32 srate)
 {
-       u8 *val;
        u32 symcalc;
        u64 sval;
 
        state->symbol_rate = srate;
-
        if (state->dst_type == DST_TYPE_IS_TERR) {
                return 0;
        }
-       if (debug > 4)
-               dprintk("%s: set symrate %u\n", __FUNCTION__, srate);
+       dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
        srate /= 1000;
-       val = &state->tx_tuna[0];
-
        if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
                sval = srate;
                sval <<= 20;
                do_div(sval, 88000);
                symcalc = (u32) sval;
-
-               if (debug > 4)
-                       dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
-
-               val[5] = (u8) (symcalc >> 12);
-               val[6] = (u8) (symcalc >> 4);
-               val[7] = (u8) (symcalc << 4);
+               dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+               state->tx_tuna[5] = (u8) (symcalc >> 12);
+               state->tx_tuna[6] = (u8) (symcalc >> 4);
+               state->tx_tuna[7] = (u8) (symcalc << 4);
        } else {
-               val[5] = (u8) (srate >> 16) & 0x7f;
-               val[6] = (u8) (srate >> 8);
-               val[7] = (u8) srate;
+               state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+               state->tx_tuna[6] = (u8) (srate >> 8);
+               state->tx_tuna[7] = (u8) srate;
+       }
+       state->tx_tuna[8] &= ~0x20;
+       if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+               if (srate > 8000)
+                       state->tx_tuna[8] |= 0x20;
        }
-       val[8] &= ~0x20;
-       if (srate > 8000)
-               val[8] |= 0x20;
        return 0;
 }
 
@@ -496,32 +477,27 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
 
        state->modulation = modulation;
        switch (modulation) {
-               case QAM_16:
-                       state->tx_tuna[8] = 0x10;
-                       break;
-
-               case QAM_32:
-                       state->tx_tuna[8] = 0x20;
-                       break;
-
-               case QAM_64:
-                       state->tx_tuna[8] = 0x40;
-                       break;
-
-               case QAM_128:
-                       state->tx_tuna[8] = 0x80;
-                       break;
-
-               case QAM_256:
-                       state->tx_tuna[8] = 0x00;
-                       break;
-
-               case QPSK:
-               case QAM_AUTO:
-               case VSB_8:
-               case VSB_16:
-               default:
-                       return -EINVAL;
+       case QAM_16:
+               state->tx_tuna[8] = 0x10;
+               break;
+       case QAM_32:
+               state->tx_tuna[8] = 0x20;
+               break;
+       case QAM_64:
+               state->tx_tuna[8] = 0x40;
+               break;
+       case QAM_128:
+               state->tx_tuna[8] = 0x80;
+               break;
+       case QAM_256:
+               state->tx_tuna[8] = 0x00;
+               break;
+       case QPSK:
+       case QAM_AUTO:
+       case VSB_8:
+       case VSB_16:
+       default:
+               return -EINVAL;
 
        }
 
@@ -534,7 +510,7 @@ static fe_modulation_t dst_get_modulation(struct dst_state *state)
 }
 
 
-u8 dst_check_sum(u8 * buf, u32 len)
+u8 dst_check_sum(u8 *buf, u32 len)
 {
        u32 i;
        u8 val = 0;
@@ -549,26 +525,24 @@ EXPORT_SYMBOL(dst_check_sum);
 
 static void dst_type_flags_print(u32 type_flags)
 {
-       printk("DST type flags :");
+       dprintk(verbose, DST_ERROR, 0, "DST type flags :");
        if (type_flags & DST_TYPE_HAS_NEWTUNE)
-               printk(" 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+               dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
        if (type_flags & DST_TYPE_HAS_TS204)
-               printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
+               dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
        if (type_flags & DST_TYPE_HAS_SYMDIV)
-               printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+               dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
        if (type_flags & DST_TYPE_HAS_FW_1)
-               printk(" 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+               dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
        if (type_flags & DST_TYPE_HAS_FW_2)
-               printk(" 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+               dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
        if (type_flags & DST_TYPE_HAS_FW_3)
-               printk(" 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
-//     if ((type_flags & DST_TYPE_HAS_FW_BUILD) && new_fw)
-
-       printk("\n");
+               dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
+       dprintk(verbose, DST_ERROR, 0, "\n");
 }
 
 
-static int dst_type_print (u8 type)
+static int dst_type_print(u8 type)
 {
        char *otype;
        switch (type) {
@@ -585,10 +559,10 @@ static int dst_type_print (u8 type)
                break;
 
        default:
-               printk("%s: invalid dst type %d\n", __FUNCTION__, type);
+               dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
                return -EINVAL;
        }
-       printk("DST type : %s\n", otype);
+       dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
 
        return 0;
 }
@@ -700,7 +674,7 @@ struct dst_types dst_tlist[] = {
                .offset = 1,
                .dst_type = DST_TYPE_IS_CABLE,
                .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
-                                                       | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+                                                       | DST_TYPE_HAS_FW_2,
                .dst_feature = DST_TYPE_HAS_CA
        },
 
@@ -708,7 +682,7 @@ struct dst_types dst_tlist[] = {
                .device_id = "DCTNEW",
                .offset = 1,
                .dst_type = DST_TYPE_IS_CABLE,
-               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3,
+               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
                .dst_feature = 0
        },
 
@@ -716,7 +690,7 @@ struct dst_types dst_tlist[] = {
                .device_id = "DTT-CI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_TERR,
-               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
                .dst_feature = 0
        },
 
@@ -756,6 +730,71 @@ struct dst_types dst_tlist[] = {
 
 };
 
+static int dst_get_mac(struct dst_state *state)
+{
+       u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       get_mac[7] = dst_check_sum(get_mac, 7);
+       if (dst_command(state, get_mac, 8) < 0) {
+               dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+               return -1;
+       }
+       memset(&state->mac_address, '\0', 8);
+       memcpy(&state->mac_address, &state->rxbuffer, 6);
+       dprintk(verbose, DST_ERROR, 1, "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]",
+               state->mac_address[0], state->mac_address[1], state->mac_address[2],
+               state->mac_address[4], state->mac_address[5], state->mac_address[6]);
+
+       return 0;
+}
+
+static int dst_fw_ver(struct dst_state *state)
+{
+       u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       get_ver[7] = dst_check_sum(get_ver, 7);
+       if (dst_command(state, get_ver, 8) < 0) {
+               dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+               return -1;
+       }
+       memset(&state->fw_version, '\0', 8);
+       memcpy(&state->fw_version, &state->rxbuffer, 8);
+       dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
+               state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
+               state->fw_version[1],
+               state->fw_version[5], state->fw_version[6],
+               state->fw_version[4], state->fw_version[3], state->fw_version[2]);
+
+       return 0;
+}
+
+static int dst_card_type(struct dst_state *state)
+{
+       u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       get_type[7] = dst_check_sum(get_type, 7);
+       if (dst_command(state, get_type, 8) < 0) {
+               dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+               return -1;
+       }
+       memset(&state->card_info, '\0', 8);
+       memcpy(&state->card_info, &state->rxbuffer, 8);
+       dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
+
+       return 0;
+}
+
+static int dst_get_vendor(struct dst_state *state)
+{
+       u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       get_vendor[7] = dst_check_sum(get_vendor, 7);
+       if (dst_command(state, get_vendor, 8) < 0) {
+               dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+               return -1;
+       }
+       memset(&state->vendor, '\0', 8);
+       memcpy(&state->vendor, &state->rxbuffer, 8);
+       dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
+
+       return 0;
+}
 
 static int dst_get_device_id(struct dst_state *state)
 {
@@ -772,53 +811,45 @@ static int dst_get_device_id(struct dst_state *state)
 
        if (write_dst(state, device_type, FIXED_COMM))
                return -1;              /*      Write failed            */
-
        if ((dst_pio_disable(state)) < 0)
                return -1;
-
        if (read_dst(state, &reply, GET_ACK))
                return -1;              /*      Read failure            */
-
        if (reply != ACK) {
-               dprintk("%s: Write not Acknowledged! [Reply=0x%02x]\n", __FUNCTION__, reply);
+               dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
                return -1;              /*      Unack'd write           */
        }
-
        if (!dst_wait_dst_ready(state, DEVICE_INIT))
                return -1;              /*      DST not ready yet       */
-
        if (read_dst(state, state->rxbuffer, FIXED_COMM))
                return -1;
 
        dst_pio_disable(state);
-
        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
-               dprintk("%s: Checksum failure! \n", __FUNCTION__);
+               dprintk(verbose, DST_INFO, 1, "Checksum failure!");
                return -1;              /*      Checksum failure        */
        }
-
        state->rxbuffer[7] = '\0';
 
-       for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE (dst_tlist); i++, p_dst_type++) {
+       for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
                if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
                        use_type_flags = p_dst_type->type_flags;
                        use_dst_type = p_dst_type->dst_type;
 
                        /*      Card capabilities       */
                        state->dst_hw_cap = p_dst_type->dst_feature;
-                       printk ("%s: Recognise [%s]\n", __FUNCTION__, p_dst_type->device_id);
+                       dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
 
                        break;
                }
        }
 
        if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
-               printk("%s: Unable to recognize %s or %s\n", __FUNCTION__, &state->rxbuffer[0], &state->rxbuffer[1]);
-               printk("%s: please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
+               dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
                use_dst_type = DST_TYPE_IS_SAT;
                use_type_flags = DST_TYPE_HAS_SYMDIV;
        }
-
        dst_type_print(use_dst_type);
        state->type_flags = use_type_flags;
        state->dst_type = use_dst_type;
@@ -834,7 +865,7 @@ static int dst_get_device_id(struct dst_state *state)
 static int dst_probe(struct dst_state *state)
 {
        if ((rdc_8820_reset(state)) < 0) {
-               dprintk("%s: RDC 8820 RESET Failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
                return -1;
        }
        if (dst_addons & DST_TYPE_HAS_CA)
@@ -843,80 +874,87 @@ static int dst_probe(struct dst_state *state)
                msleep(100);
 
        if ((dst_comm_init(state)) < 0) {
-               dprintk("%s: DST Initialization Failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
                return -1;
        }
        msleep(100);
        if (dst_get_device_id(state) < 0) {
-               dprintk("%s: unknown device.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "unknown device.");
                return -1;
        }
+       if (dst_get_mac(state) < 0) {
+               dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
+               return 0;
+       }
+       if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
+               if (dst_fw_ver(state) < 0) {
+                       dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
+                       return 0;
+               }
+               if (dst_card_type(state) < 0) {
+                       dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
+                       return 0;
+               }
+               if (dst_get_vendor(state) < 0) {
+                       dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
+                       return 0;
+               }
+       }
 
        return 0;
 }
 
-int dst_command(struct dst_state* state, u8 * data, u8 len)
+int dst_command(struct dst_state *state, u8 *data, u8 len)
 {
        u8 reply;
        if ((dst_comm_init(state)) < 0) {
-               dprintk("%s: DST Communication Initialization Failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
                return -1;
        }
-
        if (write_dst(state, data, len)) {
-               if (verbose > 1)
-                       dprintk("%s: Tring to recover.. \n", __FUNCTION__);
+               dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
                if ((dst_error_recovery(state)) < 0) {
-                       dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+                       dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
                        return -1;
                }
                return -1;
        }
        if ((dst_pio_disable(state)) < 0) {
-               dprintk("%s: PIO Disable Failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
                return -1;
        }
        if (state->type_flags & DST_TYPE_HAS_FW_1)
                udelay(3000);
-
        if (read_dst(state, &reply, GET_ACK)) {
-               if (verbose > 1)
-                       dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
                if ((dst_error_recovery(state)) < 0) {
-                       dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+                       dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
                        return -1;
                }
                return -1;
        }
-
        if (reply != ACK) {
-               dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+               dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
                return -1;
        }
        if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
                return 0;
-
-//     udelay(3000);
        if (state->type_flags & DST_TYPE_HAS_FW_1)
                udelay(3000);
        else
                udelay(2000);
-
        if (!dst_wait_dst_ready(state, NO_DELAY))
                return -1;
-
        if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
-               if (verbose > 1)
-                       dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
                if ((dst_error_recovery(state)) < 0) {
-                       dprintk("%s: Recovery failed.\n", __FUNCTION__);
+                       dprintk(verbose, DST_INFO, 1, "Recovery failed.");
                        return -1;
                }
                return -1;
        }
-
        if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
-               dprintk("%s: checksum failure\n", __FUNCTION__);
+               dprintk(verbose, DST_INFO, 1, "checksum failure");
                return -1;
        }
 
@@ -924,11 +962,11 @@ int dst_command(struct dst_state* state, u8 * data, u8 len)
 }
 EXPORT_SYMBOL(dst_command);
 
-static int dst_get_signal(struct dst_statestate)
+static int dst_get_signal(struct dst_state *state)
 {
        int retval;
        u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
-       dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
+       //dprintk("%s: Getting Signal strength and other parameters\n", __FUNCTION__);
        if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
                state->decode_lock = state->decode_strength = state->decode_snr = 0;
                return 0;
@@ -955,13 +993,12 @@ static int dst_get_signal(struct dst_state* state)
        return 0;
 }
 
-static int dst_tone_power_cmd(struct dst_statestate)
+static int dst_tone_power_cmd(struct dst_state *state)
 {
        u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
 
        if (state->dst_type == DST_TYPE_IS_TERR)
                return 0;
-
        paket[4] = state->tx_tuna[4];
        paket[2] = state->tx_tuna[2];
        paket[3] = state->tx_tuna[3];
@@ -971,61 +1008,53 @@ static int dst_tone_power_cmd(struct dst_state* state)
        return 0;
 }
 
-static int dst_get_tuna(struct dst_statestate)
+static int dst_get_tuna(struct dst_state *state)
 {
        int retval;
 
        if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
                return 0;
-
        state->diseq_flags &= ~(HAS_LOCK);
        if (!dst_wait_dst_ready(state, NO_DELAY))
                return 0;
-
-       if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+       if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
                /* how to get variable length reply ???? */
                retval = read_dst(state, state->rx_tuna, 10);
-       } else {
+       else
                retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
-       }
-
        if (retval < 0) {
-               dprintk("%s: read not successful\n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "read not successful");
                return 0;
        }
-
        if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
-                       dprintk("%s: checksum failure?\n", __FUNCTION__);
+                       dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
                        return 0;
                }
        } else {
                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
-                       dprintk("%s: checksum failure?\n", __FUNCTION__);
+                       dprintk(verbose, DST_INFO, 1, "checksum failure? ");
                        return 0;
                }
        }
        if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
                return 0;
        state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
-
        state->decode_lock = 1;
        state->diseq_flags |= HAS_LOCK;
 
        return 1;
 }
 
-static int dst_set_voltage(struct dvb_frontendfe, fe_sec_voltage_t voltage);
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
 
-static int dst_write_tuna(struct dvb_frontendfe)
+static int dst_write_tuna(struct dvb_frontend *fe)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
        int retval;
        u8 reply;
 
-       if (debug > 4)
-               dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
-
+       dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
        state->decode_freq = 0;
        state->decode_lock = state->decode_strength = state->decode_snr = 0;
        if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1035,35 +1064,31 @@ static int dst_write_tuna(struct dvb_frontend* fe)
        state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
 
        if ((dst_comm_init(state)) < 0) {
-               dprintk("%s: DST Communication initialization failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
                return -1;
        }
-
        if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
                retval = write_dst(state, &state->tx_tuna[0], 10);
-
        } else {
                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
                retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
        }
        if (retval < 0) {
                dst_pio_disable(state);
-               dprintk("%s: write not successful\n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "write not successful");
                return retval;
        }
-
        if ((dst_pio_disable(state)) < 0) {
-               dprintk("%s: DST PIO disable failed !\n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
                return -1;
        }
-
        if ((read_dst(state, &reply, GET_ACK) < 0)) {
-               dprintk("%s: read verify not successful.\n", __FUNCTION__);
+               dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
                return -1;
        }
        if (reply != ACK) {
-               dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+               dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
                return 0;
        }
        state->diseq_flags |= ATTEMPT_TUNE;
@@ -1085,14 +1110,13 @@ static int dst_write_tuna(struct dvb_frontend* fe)
  * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
  */
 
-static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
        u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
 
        if (state->dst_type != DST_TYPE_IS_SAT)
                return 0;
-
        if (cmd->msg_len == 0 || cmd->msg_len > 4)
                return -EINVAL;
        memcpy(&paket[3], cmd->msg, cmd->msg_len);
@@ -1101,65 +1125,61 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd*
        return 0;
 }
 
-static int dst_set_voltage(struct dvb_frontendfe, fe_sec_voltage_t voltage)
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
        int need_cmd;
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        state->voltage = voltage;
-
        if (state->dst_type != DST_TYPE_IS_SAT)
                return 0;
 
        need_cmd = 0;
-       switch (voltage) {
-               case SEC_VOLTAGE_13:
-               case SEC_VOLTAGE_18:
-                       if ((state->diseq_flags & HAS_POWER) == 0)
-                               need_cmd = 1;
-                       state->diseq_flags |= HAS_POWER;
-                       state->tx_tuna[4] = 0x01;
-                       break;
 
-               case SEC_VOLTAGE_OFF:
+       switch (voltage) {
+       case SEC_VOLTAGE_13:
+       case SEC_VOLTAGE_18:
+               if ((state->diseq_flags & HAS_POWER) == 0)
                        need_cmd = 1;
-                       state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
-                       state->tx_tuna[4] = 0x00;
-                       break;
-
-               default:
-                       return -EINVAL;
+               state->diseq_flags |= HAS_POWER;
+               state->tx_tuna[4] = 0x01;
+               break;
+       case SEC_VOLTAGE_OFF:
+               need_cmd = 1;
+               state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
+               state->tx_tuna[4] = 0x00;
+               break;
+       default:
+               return -EINVAL;
        }
+
        if (need_cmd)
                dst_tone_power_cmd(state);
 
        return 0;
 }
 
-static int dst_set_tone(struct dvb_frontendfe, fe_sec_tone_mode_t tone)
+static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        state->tone = tone;
-
        if (state->dst_type != DST_TYPE_IS_SAT)
                return 0;
 
        switch (tone) {
-               case SEC_TONE_OFF:
-                       if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
-                           state->tx_tuna[2] = 0x00;
-                       else
-                           state->tx_tuna[2] = 0xff;
-
-                       break;
-
-               case SEC_TONE_ON:
-                       state->tx_tuna[2] = 0x02;
-                       break;
+       case SEC_TONE_OFF:
+               if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+                   state->tx_tuna[2] = 0x00;
+               else
+                   state->tx_tuna[2] = 0xff;
+               break;
 
-               default:
-                       return -EINVAL;
+       case SEC_TONE_ON:
+               state->tx_tuna[2] = 0x02;
+               break;
+       default:
+               return -EINVAL;
        }
        dst_tone_power_cmd(state);
 
@@ -1172,16 +1192,14 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
 
        if (state->dst_type != DST_TYPE_IS_SAT)
                return 0;
-
        state->minicmd = minicmd;
-
        switch (minicmd) {
-               case SEC_MINI_A:
-                       state->tx_tuna[3] = 0x02;
-                       break;
-               case SEC_MINI_B:
-                       state->tx_tuna[3] = 0xff;
-                       break;
+       case SEC_MINI_A:
+               state->tx_tuna[3] = 0x02;
+               break;
+       case SEC_MINI_B:
+               state->tx_tuna[3] = 0xff;
+               break;
        }
        dst_tone_power_cmd(state);
 
@@ -1189,42 +1207,37 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
 }
 
 
-static int dst_init(struct dvb_frontendfe)
+static int dst_init(struct dvb_frontend *fe)
 {
-       struct dst_state* state = fe->demodulator_priv;
-       static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
-       static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
-       static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-       static u8 ini_tvci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-       static u8 ini_cabfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-       static u8 ini_cabci_tuna[] = { 9, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
-//     state->inversion = INVERSION_ON;
+       struct dst_state *state = fe->demodulator_priv;
+
+       static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
+       static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
+       static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+       static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+       static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+       static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+
        state->inversion = INVERSION_OFF;
        state->voltage = SEC_VOLTAGE_13;
        state->tone = SEC_TONE_OFF;
-       state->symbol_rate = 29473000;
-       state->fec = FEC_AUTO;
        state->diseq_flags = 0;
        state->k22 = 0x02;
        state->bandwidth = BANDWIDTH_7_MHZ;
        state->cur_jiff = jiffies;
-       if (state->dst_type == DST_TYPE_IS_SAT) {
-               state->frequency = 950000;
-               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_satci_tuna : ini_satfta_tuna), sizeof(ini_satfta_tuna));
-       } else if (state->dst_type == DST_TYPE_IS_TERR) {
-               state->frequency = 137000000;
-               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_tvci_tuna : ini_tvfta_tuna), sizeof(ini_tvfta_tuna));
-       } else if (state->dst_type == DST_TYPE_IS_CABLE) {
-               state->frequency = 51000000;
-               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ini_cabci_tuna : ini_cabfta_tuna), sizeof(ini_cabfta_tuna));
-       }
+       if (state->dst_type == DST_TYPE_IS_SAT)
+               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+       else if (state->dst_type == DST_TYPE_IS_TERR)
+               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+       else if (state->dst_type == DST_TYPE_IS_CABLE)
+               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
 
        return 0;
 }
 
-static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
+static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        *status = 0;
        if (state->diseq_flags & HAS_LOCK) {
@@ -1236,9 +1249,9 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
        return 0;
 }
 
-static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        dst_get_signal(state);
        *strength = state->decode_strength;
@@ -1246,9 +1259,9 @@ static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
        return 0;
 }
 
-static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
+static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        dst_get_signal(state);
        *snr = state->decode_snr;
@@ -1256,28 +1269,24 @@ static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
        return 0;
 }
 
-static int dst_set_frontend(struct dvb_frontendfe, struct dvb_frontend_parameters *p)
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        dst_set_freq(state, p->frequency);
-       if (verbose > 4)
-               dprintk("Set Frequency=[%d]\n", p->frequency);
+       dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
 
-//     dst_set_inversion(state, p->inversion);
        if (state->dst_type == DST_TYPE_IS_SAT) {
                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
                        dst_set_inversion(state, p->inversion);
-
                dst_set_fec(state, p->u.qpsk.fec_inner);
                dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
                dst_set_polarization(state);
-               if (verbose > 4)
-                       dprintk("Set Symbolrate=[%d]\n", p->u.qpsk.symbol_rate);
+               dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
 
-       } else if (state->dst_type == DST_TYPE_IS_TERR) {
+       } else if (state->dst_type == DST_TYPE_IS_TERR)
                dst_set_bandwidth(state, p->u.ofdm.bandwidth);
-       else if (state->dst_type == DST_TYPE_IS_CABLE) {
+       else if (state->dst_type == DST_TYPE_IS_CABLE) {
                dst_set_fec(state, p->u.qam.fec_inner);
                dst_set_symbolrate(state, p->u.qam.symbol_rate);
                dst_set_modulation(state, p->u.qam.modulation);
@@ -1287,16 +1296,14 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
        return 0;
 }
 
-static int dst_get_frontend(struct dvb_frontendfe, struct dvb_frontend_parameters *p)
+static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
 
        p->frequency = state->decode_freq;
-//     p->inversion = state->inversion;
        if (state->dst_type == DST_TYPE_IS_SAT) {
                if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
                        p->inversion = state->inversion;
-
                p->u.qpsk.symbol_rate = state->symbol_rate;
                p->u.qpsk.fec_inner = dst_get_fec(state);
        } else if (state->dst_type == DST_TYPE_IS_TERR) {
@@ -1304,16 +1311,15 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
        } else if (state->dst_type == DST_TYPE_IS_CABLE) {
                p->u.qam.symbol_rate = state->symbol_rate;
                p->u.qam.fec_inner = dst_get_fec(state);
-//             p->u.qam.modulation = QAM_AUTO;
                p->u.qam.modulation = dst_get_modulation(state);
        }
 
        return 0;
 }
 
-static void dst_release(struct dvb_frontendfe)
+static void dst_release(struct dvb_frontend *fe)
 {
-       struct dst_statestate = fe->demodulator_priv;
+       struct dst_state *state = fe->demodulator_priv;
        kfree(state);
 }
 
@@ -1321,9 +1327,8 @@ static struct dvb_frontend_ops dst_dvbt_ops;
 static struct dvb_frontend_ops dst_dvbs_ops;
 static struct dvb_frontend_ops dst_dvbc_ops;
 
-struct dst_statedst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
+struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
 {
-
        /* check if the ASIC is there */
        if (dst_probe(state) < 0) {
                if (state)
@@ -1336,17 +1341,14 @@ struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
        case DST_TYPE_IS_TERR:
                memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
                break;
-
        case DST_TYPE_IS_CABLE:
                memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
                break;
-
        case DST_TYPE_IS_SAT:
                memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
                break;
-
        default:
-               printk("%s: unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n", __FUNCTION__);
+               dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
                if (state)
                        kfree(state);
 
@@ -1374,12 +1376,9 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
        },
 
        .release = dst_release,
-
        .init = dst_init,
-
        .set_frontend = dst_set_frontend,
        .get_frontend = dst_get_frontend,
-
        .read_status = dst_read_status,
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
@@ -1401,16 +1400,12 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
        },
 
        .release = dst_release,
-
        .init = dst_init,
-
        .set_frontend = dst_set_frontend,
        .get_frontend = dst_get_frontend,
-
        .read_status = dst_read_status,
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
-
        .diseqc_send_burst = dst_send_burst,
        .diseqc_send_master_cmd = dst_set_diseqc,
        .set_voltage = dst_set_voltage,
@@ -1432,18 +1427,14 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
        },
 
        .release = dst_release,
-
        .init = dst_init,
-
        .set_frontend = dst_set_frontend,
        .get_frontend = dst_get_frontend,
-
        .read_status = dst_read_status,
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
 };
 
-
 MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
 MODULE_AUTHOR("Jamie Honan, Manu Abraham");
 MODULE_LICENSE("GPL");
index bfaacd5fc20f01b1663132c30e281e794f049c86..6776a592045f36d7468d18baedffc32b5740bfeb 100644 (file)
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
-
 #include <linux/dvb/ca.h>
 #include "dvbdev.h"
 #include "dvb_frontend.h"
-
 #include "dst_ca.h"
 #include "dst_common.h"
 
+#define DST_CA_ERROR           0
+#define DST_CA_NOTICE          1
+#define DST_CA_INFO            2
+#define DST_CA_DEBUG           3
+
+#define dprintk(x, y, z, format, arg...) do {                                          \
+       if (z) {                                                                        \
+               if      ((x > DST_CA_ERROR) && (x > y))                                 \
+                       printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);      \
+               else if ((x > DST_CA_NOTICE) && (x > y))                                \
+                       printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);   \
+               else if ((x > DST_CA_INFO) && (x > y))                                  \
+                       printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);     \
+               else if ((x > DST_CA_DEBUG) && (x > y))                                 \
+                       printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);    \
+       } else {                                                                        \
+               if (x > y)                                                              \
+                       printk(format, ## arg);                                         \
+       }                                                                               \
+} while(0)
+
+
 static unsigned int verbose = 5;
 module_param(verbose, int, 0644);
 MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
 
-static unsigned int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug messages, default is 1 (yes)");
-
-#define dprintk if (debug) printk
-
 /*     Need some more work     */
 static int ca_set_slot_descr(void)
 {
@@ -61,27 +73,20 @@ static int put_checksum(u8 *check_string, int length)
 {
        u8 i = 0, checksum = 0;
 
-       if (verbose > 3) {
-               dprintk("%s: ========================= Checksum calculation ===========================\n", __FUNCTION__);
-               dprintk("%s: String Length=[0x%02x]\n", __FUNCTION__, length);
+       dprintk(verbose, DST_CA_DEBUG, 1, " ========================= Checksum calculation ===========================");
+       dprintk(verbose, DST_CA_DEBUG, 1, " String Length=[0x%02x]", length);
+       dprintk(verbose, DST_CA_DEBUG, 1, " String=[");
 
-               dprintk("%s: String=[", __FUNCTION__);
-       }
        while (i < length) {
-               if (verbose > 3)
-                       dprintk(" %02x", check_string[i]);
+               dprintk(verbose, DST_CA_DEBUG, 0, " %02x", check_string[i]);
                checksum += check_string[i];
                i++;
        }
-       if (verbose > 3) {
-               dprintk(" ]\n");
-               dprintk("%s: Sum=[%02x]\n", __FUNCTION__, checksum);
-       }
+       dprintk(verbose, DST_CA_DEBUG, 0, " ]\n");
+       dprintk(verbose, DST_CA_DEBUG, 1, "Sum=[%02x]\n", checksum);
        check_string[length] = ~checksum + 1;
-       if (verbose > 3) {
-               dprintk("%s: Checksum=[%02x]\n", __FUNCTION__, check_string[length]);
-               dprintk("%s: ==========================================================================\n", __FUNCTION__);
-       }
+       dprintk(verbose, DST_CA_DEBUG, 1, " Checksum=[%02x]", check_string[length]);
+       dprintk(verbose, DST_CA_DEBUG, 1, " ==========================================================================");
 
        return 0;
 }
@@ -94,30 +99,26 @@ static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8
        msleep(65);
 
        if (write_dst(state, data, len)) {
-               dprintk("%s: Write not successful, trying to recover\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
                dst_error_recovery(state);
                return -1;
        }
-
        if ((dst_pio_disable(state)) < 0) {
-               dprintk("%s: DST PIO disable failed.\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
                return -1;
        }
-
        if (read_dst(state, &reply, GET_ACK) < 0) {
-               dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
                dst_error_recovery(state);
                return -1;
        }
-
        if (read) {
                if (! dst_wait_dst_ready(state, LONG_DELAY)) {
-                       dprintk("%s: 8820 not ready\n", __FUNCTION__);
+                       dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
                        return -1;
                }
-
                if (read_dst(state, ca_string, 128) < 0) {      /*      Try to make this dynamic        */
-                       dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+                       dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
                        dst_error_recovery(state);
                        return -1;
                }
@@ -133,8 +134,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
 
        while (dst_ca_comm_err < RETRIES) {
                dst_comm_init(state);
-               if (verbose > 2)
-                       dprintk("%s: Put Command\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
                if (dst_ci_command(state, data, ca_string, len, read)) {        // If error
                        dst_error_recovery(state);
                        dst_ca_comm_err++; // work required here.
@@ -153,18 +153,15 @@ static int ca_get_app_info(struct dst_state *state)
 
        put_checksum(&command[0], command[0]);
        if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
-               dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
                return -1;
        }
-       if (verbose > 1) {
-               dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
-
-               dprintk("%s: ================================ CI Module Application Info ======================================\n", __FUNCTION__);
-               dprintk("%s: Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]\n",
-                       __FUNCTION__, state->messages[7], (state->messages[8] << 8) | state->messages[9],
-                       (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
-               dprintk("%s: ==================================================================================================\n", __FUNCTION__);
-       }
+       dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+       dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
+       dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
+               state->messages[7], (state->messages[8] << 8) | state->messages[9],
+               (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+       dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 
        return 0;
 }
@@ -177,31 +174,26 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
 
        put_checksum(&slot_command[0], slot_command[0]);
        if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
-               dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
                return -1;
        }
-       if (verbose > 1)
-               dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !");
 
        /*      Will implement the rest soon            */
 
-       if (verbose > 1) {
-               dprintk("%s: Slot cap = [%d]\n", __FUNCTION__, slot_cap[7]);
-               dprintk("===================================\n");
-               for (i = 0; i < 8; i++)
-                       dprintk(" %d", slot_cap[i]);
-               dprintk("\n");
-       }
+       dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
+       dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+       for (i = 0; i < 8; i++)
+               dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
+       dprintk(verbose, DST_CA_INFO, 0, "\n");
 
        p_ca_caps->slot_num = 1;
        p_ca_caps->slot_type = 1;
        p_ca_caps->descr_num = slot_cap[7];
        p_ca_caps->descr_type = 1;
 
-
-       if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps))) {
+       if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps)))
                return -EFAULT;
-       }
 
        return 0;
 }
@@ -222,46 +214,37 @@ static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_s
 
        put_checksum(&slot_command[0], 7);
        if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
-               dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
                return -1;
        }
-       if (verbose > 1)
-               dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
 
        /*      Will implement the rest soon            */
 
-       if (verbose > 1) {
-               dprintk("%s: Slot info = [%d]\n", __FUNCTION__, slot_info[3]);
-               dprintk("===================================\n");
-               for (i = 0; i < 8; i++)
-                       dprintk(" %d", slot_info[i]);
-               dprintk("\n");
-       }
+       dprintk(verbose, DST_CA_INFO, 1, " Slot info = [%d]", slot_info[3]);
+       dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+       for (i = 0; i < 8; i++)
+               dprintk(verbose, DST_CA_INFO, 0, " %d", slot_info[i]);
+       dprintk(verbose, DST_CA_INFO, 0, "\n");
 
        if (slot_info[4] & 0x80) {
                p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
                p_ca_slot_info->num = 1;
                p_ca_slot_info->type = CA_CI;
-       }
-       else if (slot_info[4] & 0x40) {
+       } else if (slot_info[4] & 0x40) {
                p_ca_slot_info->flags = CA_CI_MODULE_READY;
                p_ca_slot_info->num = 1;
                p_ca_slot_info->type = CA_CI;
-       }
-       else {
+       } else
                p_ca_slot_info->flags = 0;
-       }
 
-       if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info))) {
+       if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
                return -EFAULT;
-       }
 
        return 0;
 }
 
 
-
-
 static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
 {
        u8 i = 0;
@@ -270,24 +253,21 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
        if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
                return -EFAULT;
 
-
        if (p_ca_message->msg) {
-               if (verbose > 3)
-                       dprintk("Message = [%02x %02x %02x]\n", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
+               dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
 
                for (i = 0; i < 3; i++) {
                        command = command | p_ca_message->msg[i];
                        if (i < 2)
                                command = command << 8;
                }
-               if (verbose > 3)
-                       dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+               dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
 
                switch (command) {
-                       case CA_APP_INFO:
-                               memcpy(p_ca_message->msg, state->messages, 128);
-                               if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
-                                       return -EFAULT;
+               case CA_APP_INFO:
+                       memcpy(p_ca_message->msg, state->messages, 128);
+                       if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
+                               return -EFAULT;
                        break;
                }
        }
@@ -298,10 +278,13 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
 static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
 {
        if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
-               hw_buffer->msg[2] = p_ca_message->msg[1];               /*              MSB                     */
-               hw_buffer->msg[3] = p_ca_message->msg[2];               /*              LSB                     */
-       }
-       else {
+               hw_buffer->msg[2] = p_ca_message->msg[1];       /*      MSB     */
+               hw_buffer->msg[3] = p_ca_message->msg[2];       /*      LSB     */
+       } else {
+               if (length > 247) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " Message too long ! *** Bailing Out *** !");
+                       return -1;
+               }
                hw_buffer->msg[0] = (length & 0xff) + 7;
                hw_buffer->msg[1] = 0x40;
                hw_buffer->msg[2] = 0x03;
@@ -309,6 +292,11 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
                hw_buffer->msg[4] = 0x03;
                hw_buffer->msg[5] = length & 0xff;
                hw_buffer->msg[6] = 0x00;
+               /*
+                *      Need to compute length for EN50221 section 8.3.2, for the time being
+                *      assuming 8.3.2 is not applicable
+                */
+               memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
        }
        return 0;
 }
@@ -317,13 +305,12 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
 static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
 {
        if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
-               dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
-               dprintk("%s: Resetting DST.\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " DST-CI Command failed.");
+               dprintk(verbose, DST_CA_NOTICE, 1, " Resetting DST.");
                rdc_reset_state(state);
                return -1;
        }
-       if (verbose > 2)
-               dprintk("%s: DST-CI Command succes.\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
 
        return 0;
 }
@@ -334,130 +321,47 @@ u32 asn_1_decode(u8 *asn_1_array)
        u32 length = 0;
 
        length_field = asn_1_array[0];
-       dprintk("%s: Length field=[%02x]\n", __FUNCTION__, length_field);
+       dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
        if (length_field < 0x80) {
                length = length_field & 0x7f;
-               dprintk("%s: Length=[%02x]\n", __FUNCTION__, length);
+               dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
        } else {
                word_count = length_field & 0x7f;
                for (count = 0; count < word_count; count++) {
                        length = (length | asn_1_array[count + 1]) << 8;
-                       dprintk("%s: Length=[%04x]\n", __FUNCTION__, length);
+                       dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
                }
        }
        return length;
 }
 
-static int init_buffer(u8 *buffer, u32 length)
-{
-       u32 i;
-       for (i = 0; i < length; i++)
-               buffer[i] = 0;
-
-       return 0;
-}
-
 static int debug_string(u8 *msg, u32 length, u32 offset)
 {
        u32 i;
 
-       dprintk(" String=[ ");
+       dprintk(verbose, DST_CA_DEBUG, 0, " String=[ ");
        for (i = offset; i < length; i++)
-               dprintk("%02x ", msg[i]);
-       dprintk("]\n");
-
-       return 0;
-}
-
-static int copy_string(u8 *destination, u8 *source, u32 dest_offset, u32 source_offset, u32 length)
-{
-       u32 i;
-       dprintk("%s: Copying [", __FUNCTION__);
-       for (i = 0; i < length; i++) {
-               destination[i + dest_offset] = source[i + source_offset];
-               dprintk(" %02x", source[i + source_offset]);
-       }
-       dprintk("]\n");
-
-       return i;
-}
-
-static int modify_4_bits(u8 *message, u32 pos)
-{
-       message[pos] &= 0x0f;
+               dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]);
+       dprintk(verbose, DST_CA_DEBUG, 0, "]\n");
 
        return 0;
 }
 
-
-
 static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
 {
-       u32 length = 0, count = 0;
-       u8 asn_1_words, program_header_length;
-       u16 program_info_length = 0, es_info_length = 0;
-       u32 hw_offset = 0, buf_offset = 0, i;
-       u8 dst_tag_length;
+       u32 length = 0;
+       u8 tag_length = 8;
 
        length = asn_1_decode(&p_ca_message->msg[3]);
-       dprintk("%s: CA Message length=[%d]\n", __FUNCTION__, length);
-       dprintk("%s: ASN.1 ", __FUNCTION__);
-       debug_string(&p_ca_message->msg[4], length, 0); // length does not include tag and length
+       dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
+       debug_string(&p_ca_message->msg[4], length, 0); /*      length is excluding tag & length        */
 
-       init_buffer(hw_buffer->msg, length);
+       memset(hw_buffer->msg, '\0', length);
        handle_dst_tag(state, p_ca_message, hw_buffer, length);
+       put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
 
-       hw_offset = 7;
-       asn_1_words = 1; // just a hack to test, should compute this one
-       buf_offset = 3;
-       program_header_length = 6;
-       dst_tag_length = 7;
-
-//     debug_twinhan_ca_params(state, p_ca_message, hw_buffer, reply, query, length, hw_offset, buf_offset);
-//     dprintk("%s: Program Header(BUF)", __FUNCTION__);
-//     debug_string(&p_ca_message->msg[4], program_header_length, 0);
-//     dprintk("%s: Copying Program header\n", __FUNCTION__);
-       copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + asn_1_words), program_header_length);
-       buf_offset += program_header_length, hw_offset += program_header_length;
-       modify_4_bits(hw_buffer->msg, (hw_offset - 2));
-       if (state->type_flags & DST_TYPE_HAS_INC_COUNT) {       // workaround
-               dprintk("%s: Probably an ASIC bug !!!\n", __FUNCTION__);
-               debug_string(hw_buffer->msg, (hw_offset + program_header_length), 0);
-               hw_buffer->msg[hw_offset - 1] += 1;
-       }
-
-//     dprintk("%s: Program Header(HW), Count=[%d]", __FUNCTION__, count);
-//     debug_string(hw_buffer->msg, hw_offset, 0);
-
-       program_info_length =  ((program_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
-       dprintk("%s: Program info length=[%02x]\n", __FUNCTION__, program_info_length);
-       if (program_info_length) {
-               count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, (buf_offset + 1), (program_info_length + 1) ); // copy next elem, not current
-               buf_offset += count, hw_offset += count;
-//             dprintk("%s: Program level ", __FUNCTION__);
-//             debug_string(hw_buffer->msg, hw_offset, 0);
-       }
-
-       buf_offset += 1;// hw_offset += 1;
-       for (i = buf_offset; i < length; i++) {
-//             dprintk("%s: Stream Header ", __FUNCTION__);
-               count = copy_string(hw_buffer->msg, p_ca_message->msg, hw_offset, buf_offset, 5);
-               modify_4_bits(hw_buffer->msg, (hw_offset + 3));
-
-               hw_offset += 5, buf_offset += 5, i += 4;
-//             debug_string(hw_buffer->msg, hw_offset, (hw_offset - 5));
-               es_info_length = ((es_info_length | (p_ca_message->msg[buf_offset - 1] & 0x0f)) << 8) | p_ca_message->msg[buf_offset];
-               dprintk("%s: ES info length=[%02x]\n", __FUNCTION__, es_info_length);
-               if (es_info_length) {
-                       // copy descriptors @ STREAM level
-                       dprintk("%s: Descriptors @ STREAM level...!!! \n", __FUNCTION__);
-               }
-
-       }
-       hw_buffer->msg[length + dst_tag_length] = dst_check_sum(hw_buffer->msg, (length + dst_tag_length));
-//     dprintk("%s: Total length=[%d], Checksum=[%02x]\n", __FUNCTION__, (length + dst_tag_length), hw_buffer->msg[length + dst_tag_length]);
-       debug_string(hw_buffer->msg, (length + dst_tag_length + 1), 0); // dst tags also
-       write_to_8820(state, hw_buffer, (length + dst_tag_length + 1), reply);  // checksum
+       debug_string(hw_buffer->msg, (length + tag_length), 0); /*      tags too        */
+       write_to_8820(state, hw_buffer, (length + tag_length), reply);
 
        return 0;
 }
@@ -471,26 +375,24 @@ static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message
        /*      Do test board                   */
        /*      Not there yet but soon          */
 
-
        /*      CA PMT Reply capable            */
        if (ca_pmt_reply_test) {
                if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
-                       dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+                       dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
                        return -1;
                }
 
        /*      Process CA PMT Reply            */
        /*      will implement soon             */
-               dprintk("%s: Not there yet\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " Not there yet");
        }
        /*      CA PMT Reply not capable        */
        if (!ca_pmt_reply_test) {
                if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
-                       dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+                       dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
                        return -1;
                }
-               if (verbose > 3)
-                       dprintk("%s: ca_set_pmt.. success !\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !");
        /*      put a dummy message             */
 
        }
@@ -506,11 +408,10 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
        struct ca_msg *hw_buffer;
 
        if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
                return -ENOMEM;
        }
-       if (verbose > 3)
-               dprintk("%s\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_DEBUG, 1, " ");
 
        if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
                return -EFAULT;
@@ -525,51 +426,35 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
                        if (i < 2)
                                command = command << 8;
                }
-               if (verbose > 3)
-                       dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+               dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
 
                switch (command) {
-                       case CA_PMT:
-                               if (verbose > 3)
-//                                     dprintk("Command = SEND_CA_PMT\n");
-                                       dprintk("Command = SEND_CA_PMT\n");
-//                             if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
-                               if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {   // code simplification started
-                                       dprintk("%s: -->CA_PMT Failed !\n", __FUNCTION__);
-                                       return -1;
-                               }
-                               if (verbose > 3)
-                                       dprintk("%s: -->CA_PMT Success !\n", __FUNCTION__);
-//                             retval = dummy_set_pmt(state, p_ca_message, hw_buffer, 0, 0);
-
-                               break;
-
-                       case CA_PMT_REPLY:
-                               if (verbose > 3)
-                                       dprintk("Command = CA_PMT_REPLY\n");
-                               /*      Have to handle the 2 basic types of cards here  */
-                               if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
-                                       dprintk("%s: -->CA_PMT_REPLY Failed !\n", __FUNCTION__);
-                                       return -1;
-                               }
-                               if (verbose > 3)
-                                       dprintk("%s: -->CA_PMT_REPLY Success !\n", __FUNCTION__);
-
-                               /*      Certain boards do behave different ?            */
-//                             retval = ca_set_pmt(state, p_ca_message, hw_buffer, 1, 1);
-
-                       case CA_APP_INFO_ENQUIRY:               // only for debugging
-                               if (verbose > 3)
-                                       dprintk("%s: Getting Cam Application information\n", __FUNCTION__);
-
-                               if ((ca_get_app_info(state)) < 0) {
-                                       dprintk("%s: -->CA_APP_INFO_ENQUIRY Failed !\n", __FUNCTION__);
-                                       return -1;
-                               }
-                               if (verbose > 3)
-                                       dprintk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
-
-                               break;
+               case CA_PMT:
+                       dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
+                       if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {   // code simplification started
+                               dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
+                               return -1;
+                       }
+                       dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
+                       break;
+               case CA_PMT_REPLY:
+                       dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
+                       /*      Have to handle the 2 basic types of cards here  */
+                       if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
+                               dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
+                               return -1;
+                       }
+                       dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
+                       break;
+               case CA_APP_INFO_ENQUIRY:               // only for debugging
+                       dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
+
+                       if ((ca_get_app_info(state)) < 0) {
+                               dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
+                               return -1;
+                       }
+                       dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
+                       break;
                }
        }
        return 0;
@@ -584,121 +469,88 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        struct ca_msg *p_ca_message;
 
        if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
                return -ENOMEM;
        }
-
        if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
-               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
                return -ENOMEM;
        }
-
        if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
-               dprintk("%s: Memory allocation failure\n", __FUNCTION__);
+               dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
                return -ENOMEM;
        }
-
        /*      We have now only the standard ioctl's, the driver is upposed to handle internals.       */
        switch (cmd) {
-               case CA_SEND_MSG:
-                       if (verbose > 1)
-                               dprintk("%s: Sending message\n", __FUNCTION__);
-                       if ((ca_send_message(state, p_ca_message, arg)) < 0) {
-                               dprintk("%s: -->CA_SEND_MSG Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-
-                       break;
-
-               case CA_GET_MSG:
-                       if (verbose > 1)
-                               dprintk("%s: Getting message\n", __FUNCTION__);
-                       if ((ca_get_message(state, p_ca_message, arg)) < 0) {
-                               dprintk("%s: -->CA_GET_MSG Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-                       if (verbose > 1)
-                               dprintk("%s: -->CA_GET_MSG Success !\n", __FUNCTION__);
-
-                       break;
-
-               case CA_RESET:
-                       if (verbose > 1)
-                               dprintk("%s: Resetting DST\n", __FUNCTION__);
-                       dst_error_bailout(state);
-                       msleep(4000);
-
-                       break;
-
-               case CA_GET_SLOT_INFO:
-                       if (verbose > 1)
-                               dprintk("%s: Getting Slot info\n", __FUNCTION__);
-                       if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
-                               dprintk("%s: -->CA_GET_SLOT_INFO Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-                       if (verbose > 1)
-                               dprintk("%s: -->CA_GET_SLOT_INFO Success !\n", __FUNCTION__);
-
-                       break;
-
-               case CA_GET_CAP:
-                       if (verbose > 1)
-                               dprintk("%s: Getting Slot capabilities\n", __FUNCTION__);
-                       if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
-                               dprintk("%s: -->CA_GET_CAP Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-                       if (verbose > 1)
-                               dprintk("%s: -->CA_GET_CAP Success !\n", __FUNCTION__);
-
-                       break;
-
-               case CA_GET_DESCR_INFO:
-                       if (verbose > 1)
-                               dprintk("%s: Getting descrambler description\n", __FUNCTION__);
-                       if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
-                               dprintk("%s: -->CA_GET_DESCR_INFO Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-                       if (verbose > 1)
-                               dprintk("%s: -->CA_GET_DESCR_INFO Success !\n", __FUNCTION__);
-
-                       break;
-
-               case CA_SET_DESCR:
-                       if (verbose > 1)
-                               dprintk("%s: Setting descrambler\n", __FUNCTION__);
-                       if ((ca_set_slot_descr()) < 0) {
-                               dprintk("%s: -->CA_SET_DESCR Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-                       if (verbose > 1)
-                               dprintk("%s: -->CA_SET_DESCR Success !\n", __FUNCTION__);
-
-                       break;
-
-               case CA_SET_PID:
-                       if (verbose > 1)
-                               dprintk("%s: Setting PID\n", __FUNCTION__);
-                       if ((ca_set_pid()) < 0) {
-                               dprintk("%s: -->CA_SET_PID Failed !\n", __FUNCTION__);
-                               return -1;
-                       }
-                       if (verbose > 1)
-                               dprintk("%s: -->CA_SET_PID Success !\n", __FUNCTION__);
-
-               default:
-                       return -EOPNOTSUPP;
-               };
+       case CA_SEND_MSG:
+               dprintk(verbose, DST_CA_INFO, 1, " Sending message");
+               if ((ca_send_message(state, p_ca_message, arg)) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
+                       return -1;
+               }
+               break;
+       case CA_GET_MSG:
+               dprintk(verbose, DST_CA_INFO, 1, " Getting message");
+               if ((ca_get_message(state, p_ca_message, arg)) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
+                       return -1;
+               }
+               dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
+               break;
+       case CA_RESET:
+               dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST");
+               dst_error_bailout(state);
+               msleep(4000);
+               break;
+       case CA_GET_SLOT_INFO:
+               dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
+               if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
+                       return -1;
+               }
+               dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
+               break;
+       case CA_GET_CAP:
+               dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
+               if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
+                       return -1;
+               }
+               dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
+               break;
+       case CA_GET_DESCR_INFO:
+               dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
+               if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
+                       return -1;
+               }
+               dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
+               break;
+       case CA_SET_DESCR:
+               dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
+               if ((ca_set_slot_descr()) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
+                       return -1;
+               }
+               dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
+               break;
+       case CA_SET_PID:
+               dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
+               if ((ca_set_pid()) < 0) {
+                       dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
+                       return -1;
+               }
+               dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
+       default:
+               return -EOPNOTSUPP;
+       };
 
        return 0;
 }
 
 static int dst_ca_open(struct inode *inode, struct file *file)
 {
-       if (verbose > 4)
-               dprintk("%s:Device opened [%p]\n", __FUNCTION__, file);
+       dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
        try_module_get(THIS_MODULE);
 
        return 0;
@@ -706,27 +558,24 @@ static int dst_ca_open(struct inode *inode, struct file *file)
 
 static int dst_ca_release(struct inode *inode, struct file *file)
 {
-       if (verbose > 4)
-               dprintk("%s:Device closed.\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
        module_put(THIS_MODULE);
 
        return 0;
 }
 
-static int dst_ca_read(struct file *file, char __user * buffer, size_t length, loff_t * offset)
+static int dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
 {
        int bytes_read = 0;
 
-       if (verbose > 4)
-               dprintk("%s:Device read.\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
 
        return bytes_read;
 }
 
-static int dst_ca_write(struct file *file, const char __user * buffer, size_t length, loff_t * offset)
+static int dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
 {
-       if (verbose > 4)
-               dprintk("%s:Device write.\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_DEBUG, 1, " Device write.");
 
        return 0;
 }
@@ -751,8 +600,7 @@ static struct dvb_device dvbdev_ca = {
 int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
 {
        struct dvb_device *dvbdev;
-       if (verbose > 4)
-               dprintk("%s:registering DST-CA device\n", __FUNCTION__);
+       dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
        dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
        return 0;
 }
index ef532a6aceaa3fb4057166cea9956e6a9cb657c4..3281a6ca3685d46ea19ec12d9e88133ca228c6f8 100644 (file)
@@ -61,7 +61,6 @@
 #define        DST_TYPE_HAS_ANALOG     64      /*      Analog inputs   */
 #define DST_TYPE_HAS_SESSION   128
 
-
 #define RDC_8820_PIO_0_DISABLE 0
 #define RDC_8820_PIO_0_ENABLE  1
 #define RDC_8820_INT           2
@@ -114,6 +113,10 @@ struct dst_state {
        fe_sec_mini_cmd_t minicmd;
        fe_modulation_t modulation;
        u8 messages[256];
+       u8 mac_address[8];
+       u8 fw_version[8];
+       u8 card_info[8];
+       u8 vendor[8];
 };
 
 struct dst_types {
@@ -124,15 +127,12 @@ struct dst_types {
        u32 dst_feature;
 };
 
-
-
 struct dst_config
 {
        /* the ASIC i2c address */
        u8 demod_address;
 };
 
-
 int rdc_reset_state(struct dst_state *state);
 int rdc_8820_reset(struct dst_state *state);
 
index 6f857c6091f34ecbb9c6e5874e0049a3d5406f1e..c5c7672cd53819f9a3ab1fa391dcf039b73f9301 100644 (file)
@@ -32,9 +32,7 @@
 #include "dvbdev.h"
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
-
 #include "dvb-bt8xx.h"
-
 #include "bt878.h"
 
 static int debug;
@@ -43,9 +41,11 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
 #define dprintk( args... ) \
-       do \
+       do \
                if (debug) printk(KERN_DEBUG args); \
-       } while (0)
+       while (0)
+
+#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 
 static void dvb_bt8xx_task(unsigned long data)
 {
@@ -119,14 +119,12 @@ static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci
        unsigned int card_nr;
 
        /* Hmm, n squared. Hope n is small */
-       for (card_nr = 0; card_nr < bt878_num; card_nr++) {
+       for (card_nr = 0; card_nr < bt878_num; card_nr++)
                if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
                        return &bt878[card_nr];
-       }
        return NULL;
 }
 
-
 static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
 {
        static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };
@@ -154,16 +152,21 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
        unsigned char bs = 0;
        unsigned char cp = 0;
 
-       #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-       if (params->frequency < 542000000) cp = 0xb4;
-       else if (params->frequency < 771000000) cp = 0xbc;
-       else cp = 0xf4;
+       if (params->frequency < 542000000)
+               cp = 0xb4;
+       else if (params->frequency < 771000000)
+               cp = 0xbc;
+       else
+               cp = 0xf4;
 
-       if (params->frequency == 0) bs = 0x03;
-       else if (params->frequency < 443250000) bs = 0x02;
-       else bs = 0x08;
+       if (params->frequency == 0)
+               bs = 0x03;
+       else if (params->frequency < 443250000)
+               bs = 0x02;
+       else
+               bs = 0x08;
 
        pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
        pllbuf[1] = div >> 8;
@@ -175,7 +178,6 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
 }
 
 static struct mt352_config thomson_dtt7579_config = {
-
        .demod_address = 0x0f,
        .demod_init = thomson_dtt7579_demod_init,
        .pll_set = thomson_dtt7579_pll_set,
@@ -183,25 +185,26 @@ static struct mt352_config thomson_dtt7579_config = {
 
 static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
-   u32 freq = params->frequency;
-
-   int i, a, n, pump;
-   u32 band, pll;
+       u32 freq = params->frequency;
 
+       int i, a, n, pump;
+       u32 band, pll;
 
-   u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
-              1576000,1718000,1856000,2036000,2150000};
-   u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
-              0x00102000,0x00104000,0x00108000,0x00110000,
-              0x00120000,0x00140000};
+       u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
+               1576000,1718000,1856000,2036000,2150000};
+       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 */
+       #define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
        printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
 
        /* This is really the bit driving the tuner chip cx24108 */
 
-       if(freq<950000) freq=950000; /* kHz */
-       if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
+       if (freq<950000)
+               freq = 950000; /* kHz */
+       else if (freq>2150000)
+               freq = 2150000; /* satellite IF is 950..2150MHz */
 
        /* decide which VCO to use for the input frequency */
        for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
@@ -228,25 +231,22 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
        cx24110_pll_write(fe,0x500c0000);
        cx24110_pll_write(fe,0x83f1f800);
        cx24110_pll_write(fe,pll);
-/*        writereg(client,0x56,0x7f);*/
+       //writereg(client,0x56,0x7f);
 
        return 0;
 }
 
 static int pinnsat_pll_init(struct dvb_frontend* fe)
 {
-   return 0;
+       return 0;
 }
 
-
 static struct cx24110_config pctvsat_config = {
-
        .demod_address = 0x55,
        .pll_init = pinnsat_pll_init,
        .pll_set = cx24108_pll_set,
 };
 
-
 static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -258,15 +258,23 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
        div = (36000000 + params->frequency + 83333) / 166666;
        cfg = 0x88;
 
-       if (params->frequency < 175000000) cpump = 2;
-       else if (params->frequency < 390000000) cpump = 1;
-       else if (params->frequency < 470000000) cpump = 2;
-       else if (params->frequency < 750000000) cpump = 2;
-       else cpump = 3;
+       if (params->frequency < 175000000)
+               cpump = 2;
+       else if (params->frequency < 390000000)
+               cpump = 1;
+       else if (params->frequency < 470000000)
+               cpump = 2;
+       else if (params->frequency < 750000000)
+               cpump = 2;
+       else
+               cpump = 3;
 
-       if (params->frequency < 175000000) band_select = 0x0e;
-       else if (params->frequency < 470000000) band_select = 0x05;
-       else band_select = 0x03;
+       if (params->frequency < 175000000)
+               band_select = 0x0e;
+       else if (params->frequency < 470000000)
+               band_select = 0x05;
+       else
+               band_select = 0x03;
 
        data[0] = (div >> 8) & 0x7f;
        data[1] = div & 0xff;
@@ -285,14 +293,11 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
 }
 
 static struct sp887x_config microtune_mt7202dtf_config = {
-
        .demod_address = 0x70,
        .pll_set = microtune_mt7202dtf_pll_set,
        .request_firmware = microtune_mt7202dtf_request_firmware,
 };
 
-
-
 static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
 {
        static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
@@ -303,7 +308,6 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
        static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
        static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
 
-
        mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
        udelay(2000);
        mt352_write(fe, mt352_reset, sizeof(mt352_reset));
@@ -323,28 +327,45 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
        unsigned char bs = 0;
        unsigned char cp = 0;
 
-       #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-       if (params->frequency < 150000000) cp = 0xB4;
-       else if (params->frequency < 173000000) cp = 0xBC;
-       else if (params->frequency < 250000000) cp = 0xB4;
-       else if (params->frequency < 400000000) cp = 0xBC;
-       else if (params->frequency < 420000000) cp = 0xF4;
-       else if (params->frequency < 470000000) cp = 0xFC;
-       else if (params->frequency < 600000000) cp = 0xBC;
-       else if (params->frequency < 730000000) cp = 0xF4;
-       else cp = 0xFC;
-
-       if (params->frequency < 150000000) bs = 0x01;
-       else if (params->frequency < 173000000) bs = 0x01;
-       else if (params->frequency < 250000000) bs = 0x02;
-       else if (params->frequency < 400000000) bs = 0x02;
-       else if (params->frequency < 420000000) bs = 0x02;
-       else if (params->frequency < 470000000) bs = 0x02;
-       else if (params->frequency < 600000000) bs = 0x08;
-       else if (params->frequency < 730000000) bs = 0x08;
-       else bs = 0x08;
+       if (params->frequency < 150000000)
+               cp = 0xB4;
+       else if (params->frequency < 173000000)
+               cp = 0xBC;
+       else if (params->frequency < 250000000)
+               cp = 0xB4;
+       else if (params->frequency < 400000000)
+               cp = 0xBC;
+       else if (params->frequency < 420000000)
+               cp = 0xF4;
+       else if (params->frequency < 470000000)
+               cp = 0xFC;
+       else if (params->frequency < 600000000)
+               cp = 0xBC;
+       else if (params->frequency < 730000000)
+               cp = 0xF4;
+       else
+               cp = 0xFC;
+
+       if (params->frequency < 150000000)
+               bs = 0x01;
+       else if (params->frequency < 173000000)
+               bs = 0x01;
+       else if (params->frequency < 250000000)
+               bs = 0x02;
+       else if (params->frequency < 400000000)
+               bs = 0x02;
+       else if (params->frequency < 420000000)
+               bs = 0x02;
+       else if (params->frequency < 470000000)
+               bs = 0x02;
+       else if (params->frequency < 600000000)
+               bs = 0x08;
+       else if (params->frequency < 730000000)
+               bs = 0x08;
+       else
+               bs = 0x08;
 
        pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
        pllbuf[1] = div >> 8;
@@ -356,19 +377,15 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
 }
 
 static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
-
        .demod_address = 0x0f,
        .demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
        .pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
 };
 
-
 static struct dst_config dst_config = {
-
        .demod_address = 0x55,
 };
 
-
 static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 {
        struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
@@ -398,10 +415,8 @@ static void or51211_reset(struct dvb_frontend * fe)
         */
        /* reset & PRM1,2&4 are outputs */
        int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
-       if (ret != 0) {
-               printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR "
-                      "(%i)\n", ret);
-       }
+       if (ret != 0)
+               printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);
        bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000);   /* Reset */
        msleep(20);
        /* Now set for normal operation */
@@ -417,7 +432,6 @@ static void or51211_sleep(struct dvb_frontend * fe)
 }
 
 static struct or51211_config or51211_config = {
-
        .demod_address = 0x15,
        .request_firmware = or51211_request_firmware,
        .setmode = or51211_setmode,
@@ -425,7 +439,6 @@ static struct or51211_config or51211_config = {
        .sleep = or51211_sleep,
 };
 
-
 static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
@@ -454,12 +467,84 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 }
 
 static struct nxt6000_config vp3021_alps_tded4_config = {
-
        .demod_address = 0x0a,
        .clock_inversion = 1,
        .pll_set = vp3021_alps_tded4_pll_set,
 };
 
+static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
+{
+       static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
+       static u8 mt352_reset [] = { 0x50, 0x80 };
+       static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+       static u8 mt352_agc_cfg [] = { 0x67, 0x20, 0xa0 };
+       static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+       mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+       udelay(2000);
+       mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+       mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+       mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
+       mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+       return 0;
+}
+
+static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+{
+       u32 div;
+       struct dvb_ofdm_parameters *op = &params->u.ofdm;
+
+       div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+       pllbuf[0] = 0xc2;
+       pllbuf[1] = (div >> 8) & 0x7F;
+       pllbuf[2] = div & 0xFF;
+       pllbuf[3] = 0x85;
+
+       dprintk("frequency %u, div %u\n", params->frequency, div);
+
+       if (params->frequency < 470000000)
+               pllbuf[4] = 0x02;
+       else if (params->frequency > 823000000)
+               pllbuf[4] = 0x88;
+       else
+               pllbuf[4] = 0x08;
+
+       if (op->bandwidth == 8)
+               pllbuf[4] |= 0x04;
+
+       return 0;
+}
+
+static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
+{
+       /*
+        * Reset the frontend, must be called before trying
+        * to initialise the MT352 or mt352_attach
+        * will fail.
+        *
+        * Presumably not required for the NXT6000 frontend.
+        *
+        */
+
+       int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);
+       if (ret != 0)
+               printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);
+
+       /* Pulse the reset line */
+       bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+       bttv_write_gpio(bt->bttv_nr, 0x08, 0x00); /* Low  */
+       msleep(100);
+
+       bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+}
+
+static struct mt352_config digitv_alps_tded4_config = {
+       .demod_address = 0x0a,
+       .demod_init = digitv_alps_tded4_demod_init,
+       .pll_set = digitv_alps_tded4_pll_set,
+};
 
 static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 {
@@ -473,7 +558,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                if (card->fe != NULL) {
                        card->fe->ops->info.frequency_min = 174000000;
                        card->fe->ops->info.frequency_max = 862000000;
-                       break;
                }
                break;
 #endif
@@ -483,17 +567,28 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 #else
        case BTTV_NEBULA_DIGITV:
 #endif
+               /*
+                * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
+                * this would be a cleaner solution than trying each frontend in turn.
+                */
+
+               /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
                card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
                if (card->fe != NULL) {
+                       dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
                        break;
                }
+
+               /* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
+               digitv_alps_tded4_reset(card);
+               card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
+
+               if (card->fe != NULL)
+                       dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
                break;
 
        case BTTV_AVDVBT_761:
                card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
-               if (card->fe != NULL) {
-                       break;
-               }
                break;
 
        case BTTV_AVDVBT_771:
@@ -501,7 +596,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                if (card->fe != NULL) {
                        card->fe->ops->info.frequency_min = 174000000;
                        card->fe->ops->info.frequency_max = 862000000;
-                       break;
                }
                break;
 
@@ -522,54 +616,41 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
                /*      Attach other DST peripherals if any             */
                /*      Conditional Access device                       */
-               if (state->dst_hw_cap & DST_TYPE_HAS_CA) {
+               if (state->dst_hw_cap & DST_TYPE_HAS_CA)
                        ret = dst_ca_attach(state, &card->dvb_adapter);
-               }
-               if (card->fe != NULL) {
-                       break;
-               }
                break;
 
        case BTTV_PINNACLESAT:
                card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
-               if (card->fe != NULL) {
-                       break;
-               }
                break;
 
        case BTTV_PC_HDTV:
                card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
-               if (card->fe != NULL) {
-                       break;
-               }
                break;
        }
 
-       if (card->fe == NULL) {
+       if (card->fe == NULL)
                printk("dvb-bt8xx: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
                       card->bt->dev->vendor,
                       card->bt->dev->device,
                       card->bt->dev->subsystem_vendor,
                       card->bt->dev->subsystem_device);
-       } else {
+       else
                if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
                        printk("dvb-bt8xx: Frontend registration failed!\n");
                        if (card->fe->ops->release)
                                card->fe->ops->release(card->fe);
                        card->fe = NULL;
                }
-       }
 }
 
 static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
 {
        int result;
 
-       if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
-                                          THIS_MODULE)) < 0) {
+       if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
                printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
                return result;
-
        }
        card->dvb_adapter.priv = card;
 
@@ -664,8 +745,7 @@ static int dvb_bt8xx_probe(struct device *dev)
        strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
        card->i2c_adapter = &sub->core->i2c_adap;
 
-       switch(sub->core->type)
-       {
+       switch(sub->core->type) {
        case BTTV_PINNACLESAT:
                card->gpio_mode = 0x0400c060;
                /* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
@@ -751,7 +831,6 @@ static int dvb_bt8xx_probe(struct device *dev)
 
                kfree(card);
                return -EFAULT;
-
        }
 
        init_MUTEX(&card->bt->gpio_lock);
@@ -779,7 +858,8 @@ static int dvb_bt8xx_remove(struct device *dev)
        card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
        dvb_dmxdev_release(&card->dmxdev);
        dvb_dmx_release(&card->demux);
-       if (card->fe) dvb_unregister_frontend(card->fe);
+       if (card->fe)
+               dvb_unregister_frontend(card->fe);
        dvb_unregister_adapter(&card->dvb_adapter);
 
        kfree(card);
index 2923b3b0dd3ce3168d27964d7d78229a80d191fb..9ec8e5bd6c1fae8e60bc3c5eab60cbf61bb80b0b 100644 (file)
@@ -2,7 +2,7 @@
  * Bt8xx based DVB adapter driver
  *
  * Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
  * Copyright (C) 1999-2001 Ralph  Metzler & Marcus Metzler for convergence integrated media GmbH
  * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
  *
index 226714085f58d32b4f095dab72a6a5ffaeec0675..7cf4c4a888ec6626055380d4c7b1406799c6dfc0 100644 (file)
@@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
 config DVB_CINERGYT2_RC_QUERY_INTERVAL
        int "Infrared Remote Controller update interval [milliseconds]"
        depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
-        default "100"
+        default "50"
        help
          If you have a very fast-repeating remote control you can try lower
          values, for normal consumer receivers the default value should be
index 9ea5747b121101759808370f15f68d6e2280312e..6db0929ef53dbfa3a0e1f0875bddc037cb525ed9 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/pci.h>
@@ -36,7 +35,6 @@
 #include "dvb_demux.h"
 #include "dvb_net.h"
 
-
 #ifdef CONFIG_DVB_CINERGYT2_TUNING
        #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
        #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
@@ -49,7 +47,7 @@
        #define STREAM_URB_COUNT (32)
        #define STREAM_BUF_SIZE (512)   /* bytes */
        #define ENABLE_RC (1)
-       #define RC_QUERY_INTERVAL (100) /* milliseconds */
+       #define RC_QUERY_INTERVAL (50)  /* milliseconds */
        #define QUERY_INTERVAL (333)    /* milliseconds */
 #endif
 
@@ -142,6 +140,8 @@ struct cinergyt2 {
        struct input_dev rc_input_dev;
        struct work_struct rc_query_work;
        int rc_input_event;
+       u32 rc_last_code;
+       unsigned long last_event_jiffies;
 #endif
 };
 
@@ -156,7 +156,7 @@ struct cinergyt2_rc_event {
        uint32_t value;
 } __attribute__((packed));
 
-static const uint32_t rc_keys [] = {
+static const uint32_t rc_keys[] = {
        CINERGYT2_RC_EVENT_TYPE_NEC,    0xfe01eb04,     KEY_POWER,
        CINERGYT2_RC_EVENT_TYPE_NEC,    0xfd02eb04,     KEY_1,
        CINERGYT2_RC_EVENT_TYPE_NEC,    0xfc03eb04,     KEY_2,
@@ -685,52 +685,68 @@ static struct dvb_device cinergyt2_fe_template = {
 #ifdef ENABLE_RC
 static void cinergyt2_query_rc (void *data)
 {
-       struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data;
-       char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS };
+       struct cinergyt2 *cinergyt2 = data;
+       char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
        struct cinergyt2_rc_event rc_events[12];
-       int n, len;
+       int n, len, i;
 
        if (down_interruptible(&cinergyt2->sem))
                return;
 
        len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
-                            (char *) rc_events, sizeof(rc_events));
-
-       for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
-               int i;
+                               (char *) rc_events, sizeof(rc_events));
+       if (len < 0)
+               goto out;
+       if (len == 0) {
+               if (time_after(jiffies, cinergyt2->last_event_jiffies +
+                              msecs_to_jiffies(150))) {
+                       /* stop key repeat */
+                       if (cinergyt2->rc_input_event != KEY_MAX) {
+                               dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
+                               input_report_key(&cinergyt2->rc_input_dev,
+                                                cinergyt2->rc_input_event, 0);
+                               cinergyt2->rc_input_event = KEY_MAX;
+                       }
+                       cinergyt2->rc_last_code = ~0;
+               }
+               goto out;
+       }
+       cinergyt2->last_event_jiffies = jiffies;
 
-/*             dprintk(1,"rc_events[%d].value = %x, type=%x\n",n,le32_to_cpu(rc_events[n].value),rc_events[n].type);*/
+       for (n = 0; n < (len / sizeof(rc_events[0])); n++) {
+               dprintk(1, "rc_events[%d].value = %x, type=%x\n",
+                       n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
 
                if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
-                   rc_events[n].value == ~0)
-               {
-                       /**
-                        * keyrepeat bit. If we would handle this properly
-                        * we would need to emit down events as long the
-                        * keyrepeat goes, a up event if no further
-                        * repeat bits occur. Would need a timer to implement
-                        * and no other driver does this, so we simply
-                        * emit the last key up/down sequence again.
-                        */
+                   rc_events[n].value == ~0) {
+                       /* keyrepeat bit -> just repeat last rc_input_event */
                } else {
                        cinergyt2->rc_input_event = KEY_MAX;
-                       for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) {
-                               if (rc_keys[i+0] == rc_events[n].type &&
-                                   rc_keys[i+1] == le32_to_cpu(rc_events[n].value))
-                               {
-                                       cinergyt2->rc_input_event = rc_keys[i+2];
+                       for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) {
+                               if (rc_keys[i + 0] == rc_events[n].type &&
+                                   rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
+                                       cinergyt2->rc_input_event = rc_keys[i + 2];
                                        break;
                                }
                        }
                }
 
                if (cinergyt2->rc_input_event != KEY_MAX) {
-                       input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1);
-                       input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0);
-                       input_sync(&cinergyt2->rc_input_dev);
+                       if (rc_events[n].value == cinergyt2->rc_last_code &&
+                           cinergyt2->rc_last_code != ~0) {
+                               /* emit a key-up so the double event is recognized */
+                               dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
+                               input_report_key(&cinergyt2->rc_input_dev,
+                                                cinergyt2->rc_input_event, 0);
+                       }
+                       dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
+                       input_report_key(&cinergyt2->rc_input_dev,
+                                        cinergyt2->rc_input_event, 1);
+                       cinergyt2->rc_last_code = rc_events[n].value;
                }
        }
 
+out:
        schedule_delayed_work(&cinergyt2->rc_query_work,
                              msecs_to_jiffies(RC_QUERY_INTERVAL));
 
@@ -772,7 +788,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
                  const struct usb_device_id *id)
 {
        struct cinergyt2 *cinergyt2;
-       int i, err;
+       int err;
+#ifdef ENABLE_RC
+       int i;
+#endif
 
        if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
                dprintk(1, "out of memory?!?\n");
@@ -828,19 +847,18 @@ static int cinergyt2_probe (struct usb_interface *intf,
                            DVB_DEVICE_FRONTEND);
 
 #ifdef ENABLE_RC
-       init_input_dev(&cinergyt2->rc_input_dev);
-
-       cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY);
-       cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
-       cinergyt2->rc_input_dev.keycodemax = KEY_MAX;
+       cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+       cinergyt2->rc_input_dev.keycodesize = 0;
+       cinergyt2->rc_input_dev.keycodemax = 0;
        cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
 
-       for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3)
-               set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit);
+       for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3)
+               set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit);
 
        input_register_device(&cinergyt2->rc_input_dev);
 
        cinergyt2->rc_input_event = KEY_MAX;
+       cinergyt2->rc_last_code = ~0;
 
        INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
        schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
index fb55eaa5c8e70525073427372c9ea3f6191e3592..9719a3b30f786fee49c23a075f7a900fd32b3737 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/time.h>
+#include <linux/dvb/dmx.h>
 
 /*--------------------------------------------------------------------------*/
 /* Common definitions */
@@ -124,9 +125,7 @@ struct dmx_ts_feed {
                    u16 pid,
                    int 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* feed);
         int (*stop_filtering) (struct dmx_ts_feed* feed);
@@ -159,7 +158,6 @@ struct dmx_section_feed {
         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* feed,
                                struct dmx_section_filter** filter);
@@ -207,7 +205,6 @@ 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 */
         enum dmx_frontend_source source;
 };
 
@@ -225,8 +222,6 @@ struct dmx_frontend {
 #define DMX_MEMORY_BASED_FILTERING              8    /* write() available */
 #define DMX_CRC_CHECKING                        16
 #define DMX_TS_DESCRAMBLING                     32
-#define DMX_SECTION_PAYLOAD_DESCRAMBLING        64
-#define DMX_MAC_ADDRESS_DESCRAMBLING            128
 
 /*
  * Demux resource type identifier.
@@ -244,9 +239,7 @@ struct dmx_frontend {
 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* demux);
         int (*close) (struct dmx_demux* demux);
         int (*write) (struct dmx_demux* demux, const char* buf, size_t count);
@@ -260,17 +253,6 @@ struct dmx_demux {
                                      dmx_section_cb callback);
         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,
-                                      size_t buffer2_length,
-                                      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* demux,
                             struct dmx_frontend* frontend);
         int (*remove_frontend) (struct dmx_demux* demux,
@@ -282,20 +264,12 @@ struct dmx_demux {
 
         int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
 
+       int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
+
+       int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
+
         int (*get_stc) (struct dmx_demux* demux, unsigned int num,
                        u64 *stc, unsigned int *base);
 };
 
-/*--------------------------------------------------------------------------*/
-/* Demux directory */
-/*--------------------------------------------------------------------------*/
-
-/*
- * DMX_DIR_ENTRY(): Casts elements in the list of registered
- * demuxes from the generic type struct list_head* to the type struct dmx_demux
- *.
- */
-
-#define DMX_DIR_ENTRY(list) list_entry(list, struct dmx_demux, reg_list)
-
 #endif /* #ifndef __DEMUX_H */
index 68050cd527cb4db568a0868b10d2234bbe003ace..8028c3a5e287c8a5abe8a42b73984545df911506 100644 (file)
@@ -571,7 +571,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                                return ret;
                        }
 
-                       ret=(*secfeed)->set(*secfeed, para->pid, 32768, 0,
+                       ret=(*secfeed)->set(*secfeed, para->pid, 32768,
                                            (para->flags & DMX_CHECK_CRC) ? 1 : 0);
 
                        if (ret<0) {
@@ -654,7 +654,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
                (*tsfeed)->priv = (void *) filter;
 
                ret = (*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes,
-                                    188, 32768, 0, timeout);
+                                    32768, timeout);
 
                if (ret < 0) {
                        dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed);
@@ -929,6 +929,22 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
                dmxdev->demux->get_pes_pids(dmxdev->demux, (u16 *)parg);
                break;
 
+       case DMX_GET_CAPS:
+               if (!dmxdev->demux->get_caps) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
+               break;
+
+       case DMX_SET_SOURCE:
+               if (!dmxdev->demux->set_source) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = dmxdev->demux->set_source(dmxdev->demux, parg);
+               break;
+
        case DMX_GET_STC:
                if (!dmxdev->demux->get_stc) {
                        ret=-EINVAL;
index 0eb9aa711fb0335f44cce5d96faca15de40eb75d..88757e2634e5c85244dfb5dc79ec604b9e7c2a55 100644 (file)
@@ -47,7 +47,7 @@ MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
 
 #define dprintk if (dvb_ca_en50221_debug) printk
 
-#define INIT_TIMEOUT_SECS 5
+#define INIT_TIMEOUT_SECS 10
 
 #define HOST_LINK_BUF_SIZE 0x200
 
index ac9889d222882bc6629d5a2c90b7405496d8f740..dc476dda2b713242ab4185dab5889c7a80fab416 100644 (file)
 */
 // #define DVB_DEMUX_SECTION_LOSS_LOG
 
-
-static LIST_HEAD(dmx_muxs);
-
-
-static int dmx_register_demux(struct dmx_demux *demux)
-{
-       demux->users = 0;
-       list_add(&demux->reg_list, &dmx_muxs);
-       return 0;
-}
-
-static int dmx_unregister_demux(struct dmx_demux* demux)
-{
-       struct list_head *pos, *n, *head=&dmx_muxs;
-
-       list_for_each_safe (pos, n, head) {
-               if (DMX_DIR_ENTRY(pos) == demux) {
-                       if (demux->users>0)
-                               return -EINVAL;
-                       list_del(pos);
-                       return 0;
-               }
-       }
-
-       return -ENODEV;
-}
-
-
 /******************************************************************************
  * static inlined helper functions
  ******************************************************************************/
 
-
 static inline u16 section_length(const u8 *buf)
 {
-       return 3+((buf[1]&0x0f)<<8)+buf[2];
+       return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
 }
 
-
 static inline u16 ts_pid(const u8 *buf)
 {
-       return ((buf[1]&0x1f)<<8)+buf[2];
+       return ((buf[1] & 0x1f) << 8) + buf[2];
 }
 
-
 static inline u8 payload(const u8 *tsp)
 {
-       if (!(tsp[3] & 0x10)) // no payload?
+       if (!(tsp[3] & 0x10))   // no payload?
                return 0;
-       if (tsp[3] & 0x20) {  // adaptation field?
-               if (tsp[4] > 183)    // corrupted data?
+
+       if (tsp[3] & 0x20) {    // adaptation field?
+               if (tsp[4] > 183)       // corrupted data?
                        return 0;
                else
-                       return 184-1-tsp[4];
+                       return 184 - 1 - tsp[4];
        }
+
        return 184;
 }
 
-
-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_be (f->feed.sec.crc_val, src, len));
+       return (f->feed.sec.crc_val = crc32_be(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);
+       memcpy(d, s, len);
 }
 
-
 /******************************************************************************
  * 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;
@@ -123,32 +93,31 @@ static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u
        if (count == 0)
                return -1;
 
-       p = 188-count;
+       p = 188 - count;
 
        /*
-       cc=buf[3]&0x0f;
-       ccok=((dvbdmxfeed->cc+1)&0x0f)==cc ? 1 : 0;
-       dvbdmxfeed->cc=cc;
+       cc = buf[3] & 0x0f;
+       ccok = ((feed->cc + 1) & 0x0f) == cc;
+       feed->cc = cc;
        if (!ccok)
                printk("missed packet!\n");
        */
 
-       if (buf[1] & 0x40)  // PUSI ?
+       if (buf[1] & 0x40)      // PUSI ?
                feed->peslen = 0xfffa;
 
        feed->peslen += count;
 
-       return feed->cb.ts (&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+       return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
 }
 
-
-static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
-                                   struct dvb_demux_filter *f)
+static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
+                                         struct dvb_demux_filter *f)
 {
        u8 neq = 0;
        int i;
 
-       for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
+       for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
                u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i];
 
                if (f->maskandmode[i] & xor)
@@ -160,12 +129,11 @@ static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed,
        if (f->doneq && !neq)
                return 0;
 
-       return feed->cb.sec (feed->feed.sec.secbuf, feed->feed.sec.seclen,
-                            NULL, 0, &f->filter, DMX_OK);
+       return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
+                           NULL, 0, &f->filter, DMX_OK);
 }
 
-
-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;
@@ -195,26 +163,24 @@ static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed)
        return 0;
 }
 
-
 static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 {
        struct dmx_section_feed *sec = &feed->feed.sec;
 
 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
-       if(sec->secbufp < sec->tsfeedp)
-       {
+       if (sec->secbufp < sec->tsfeedp) {
                int i, n = sec->tsfeedp - sec->secbufp;
 
-               /* section padding is done with 0xff bytes entirely.
-               ** due to speed reasons, we won't check all of them
-               ** but just first and last
-               */
-               if(sec->secbuf[0] != 0xff || sec->secbuf[n-1] != 0xff)
-               {
+               /*
+                * Section padding is done with 0xff bytes entirely.
+                * Due to speed reasons, we won't check all of them
+                * but just first and last.
+                */
+               if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
                        printk("dvb_demux.c section ts padding loss: %d/%d\n",
                               n, sec->tsfeedp);
                        printk("dvb_demux.c pad data:");
-                       for(i = 0; i < n; i++)
+                       for (i = 0; i < n; i++)
                                printk(" %02x", sec->secbuf[i]);
                        printk("\n");
                }
@@ -226,82 +192,81 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
 }
 
 /*
-** Losless Section Demux 1.4.1 by Emard
-** Valsecchi Patrick:
-**  - middle of section A  (no PUSI)
-**  - end of section A and start of section B
-**    (with PUSI pointing to the start of the second section)
-**
-**  In this case, without feed->pusi_seen you'll receive a garbage section
-**  consisting of the end of section A. Basically because tsfeedp
-**  is incemented and the use=0 condition is not raised
-**  when the second packet arrives.
-**
-** Fix:
-** when demux is started, let feed->pusi_seen = 0 to
-** prevent initial feeding of garbage from the end of
-** previous section. When you for the first time see PUSI=1
-** then set feed->pusi_seen = 1
-*/
-static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed, const u8 *buf, u8 len)
+ * Losless Section Demux 1.4.1 by Emard
+ * Valsecchi Patrick:
+ *  - middle of section A  (no PUSI)
+ *  - end of section A and start of section B
+ *    (with PUSI pointing to the start of the second section)
+ *
+ *  In this case, without feed->pusi_seen you'll receive a garbage section
+ *  consisting of the end of section A. Basically because tsfeedp
+ *  is incemented and the use=0 condition is not raised
+ *  when the second packet arrives.
+ *
+ * Fix:
+ * when demux is started, let feed->pusi_seen = 0 to
+ * prevent initial feeding of garbage from the end of
+ * previous section. When you for the first time see PUSI=1
+ * then set feed->pusi_seen = 1
+ */
+static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
+                                             const u8 *buf, u8 len)
 {
        struct dvb_demux *demux = feed->demux;
        struct dmx_section_feed *sec = &feed->feed.sec;
        u16 limit, seclen, n;
 
-       if(sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
+       if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
                return 0;
 
-       if(sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE)
-       {
+       if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
                printk("dvb_demux.c section buffer full loss: %d/%d\n",
-                      sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE, DMX_MAX_SECFEED_SIZE);
+                      sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
+                      DMX_MAX_SECFEED_SIZE);
 #endif
                len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
        }
 
-       if(len <= 0)
+       if (len <= 0)
                return 0;
 
        demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
        sec->tsfeedp += len;
 
-       /* -----------------------------------------------------
-       ** Dump all the sections we can find in the data (Emard)
-       */
-
+       /*
+        * Dump all the sections we can find in the data (Emard)
+        */
        limit = sec->tsfeedp;
-       if(limit > DMX_MAX_SECFEED_SIZE)
-               return -1; /* internal error should never happen */
+       if (limit > DMX_MAX_SECFEED_SIZE)
+               return -1;      /* internal error should never happen */
 
        /* to be sure always set secbuf */
        sec->secbuf = sec->secbuf_base + sec->secbufp;
 
-       for(n = 0; sec->secbufp + 2 < limit; n++)
-       {
+       for (n = 0; sec->secbufp + 2 < limit; n++) {
                seclen = section_length(sec->secbuf);
-               if(seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
-                  || seclen + sec->secbufp > limit)
+               if (seclen <= 0 || seclen > DMX_MAX_SECFEED_SIZE
+                   || seclen + sec->secbufp > limit)
                        return 0;
                sec->seclen = seclen;
                sec->crc_val = ~0;
                /* dump [secbuf .. secbuf+seclen) */
-               if(feed->pusi_seen)
+               if (feed->pusi_seen)
                        dvb_dmx_swfilter_section_feed(feed);
 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
                else
                        printk("dvb_demux.c pusi not seen, discarding section data\n");
 #endif
-               sec->secbufp += seclen; /* secbufp and secbuf moving together is */
-               sec->secbuf += seclen; /* redundand but saves pointer arithmetic */
+               sec->secbufp += seclen; /* secbufp and secbuf moving together is */
+               sec->secbuf += seclen;  /* redundant but saves pointer arithmetic */
        }
 
        return 0;
 }
 
-
-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)
 {
        u8 p, count;
        int ccok, dc_i = 0;
@@ -309,10 +274,10 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
 
        count = payload(buf);
 
-       if (count == 0)  /* count == 0 if no payload or out of range */
+       if (count == 0)         /* count == 0 if no payload or out of range */
                return -1;
 
-       p = 188 - count; /* payload start */
+       p = 188 - count;        /* payload start */
 
        cc = buf[3] & 0x0f;
        ccok = ((feed->cc + 1) & 0x0f) == cc;
@@ -326,52 +291,53 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8
 
        if (!ccok || dc_i) {
 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
-               printk("dvb_demux.c discontinuity detected %d bytes lost\n", count);
-               /* those bytes under sume circumstances will again be reported
-               ** in the following dvb_dmx_swfilter_section_new
-               */
+               printk("dvb_demux.c discontinuity detected %d bytes lost\n",
+                      count);
+               /*
+                * those bytes under sume circumstances will again be reported
+                * in the following dvb_dmx_swfilter_section_new
+                */
 #endif
-               /* Discontinuity detected. Reset pusi_seen = 0 to
-               ** stop feeding of suspicious data until next PUSI=1 arrives
-               */
+               /*
+                * Discontinuity detected. Reset pusi_seen = 0 to
+                * stop feeding of suspicious data until next PUSI=1 arrives
+                */
                feed->pusi_seen = 0;
                dvb_dmx_swfilter_section_new(feed);
-               return 0;
        }
 
        if (buf[1] & 0x40) {
-               // PUSI=1 (is set), section boundary is here
+               /* PUSI=1 (is set), section boundary is here */
                if (count > 1 && buf[p] < count) {
-                       const u8 *before = buf+p+1;
+                       const u8 *before = &buf[p + 1];
                        u8 before_len = buf[p];
-                       const u8 *after = before+before_len;
-                       u8 after_len = count-1-before_len;
+                       const u8 *after = &before[before_len];
+                       u8 after_len = count - 1 - before_len;
 
-                       dvb_dmx_swfilter_section_copy_dump(feed, before, before_len);
+                       dvb_dmx_swfilter_section_copy_dump(feed, before,
+                                                          before_len);
                        /* before start of new section, set pusi_seen = 1 */
                        feed->pusi_seen = 1;
                        dvb_dmx_swfilter_section_new(feed);
-                       dvb_dmx_swfilter_section_copy_dump(feed, after, after_len);
+                       dvb_dmx_swfilter_section_copy_dump(feed, after,
+                                                          after_len);
                }
 #ifdef DVB_DEMUX_SECTION_LOSS_LOG
-               else
-                       if (count > 0)
-                               printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
+               else if (count > 0)
+                       printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
 #endif
        } else {
-               // PUSI=0 (is not set), no section boundary
-               const u8 *entire = buf+p;
-               u8 entire_len = count;
-
-               dvb_dmx_swfilter_section_copy_dump(feed, entire, entire_len);
+               /* PUSI=0 (is not set), no section boundary */
+               dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
        }
+
        return 0;
 }
 
-
-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) {
+       switch (feed->type) {
        case DMX_TYPE_TS:
                if (!feed->feed.ts.is_filtering)
                        break;
@@ -379,7 +345,8 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
                        if (feed->ts_type & TS_PAYLOAD_ONLY)
                                dvb_dmx_swfilter_payload(feed, buf);
                        else
-                               feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+                               feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
+                                           DMX_OK);
                }
                if (feed->ts_type & TS_DECODER)
                        if (feed->demux->write_to_decoder)
@@ -390,7 +357,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
                if (!feed->feed.sec.is_filtering)
                        break;
                if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
-                       feed->feed.sec.seclen = feed->feed.sec.secbufp=0;
+                       feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
                break;
 
        default:
@@ -406,7 +373,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, con
 static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
 {
        struct dvb_demux_feed *feed;
-       struct list_head *pos, *head=&demux->feed_list;
+       struct list_head *pos, *head = &demux->feed_list;
        u16 pid = ts_pid(buf);
        int dvr_done = 0;
 
@@ -432,21 +399,21 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
        }
 }
 
-void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)
+void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
+                             size_t count)
 {
        spin_lock(&demux->lock);
 
        while (count--) {
-               if(buf[0] == 0x47) {
-                       dvb_dmx_swfilter_packet(demux, buf);
-               }
+               if (buf[0] == 0x47)
+                       dvb_dmx_swfilter_packet(demux, buf);
                buf += 188;
        }
 
        spin_unlock(&demux->lock);
 }
-EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
@@ -454,8 +421,10 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 
        spin_lock(&demux->lock);
 
-       if ((i = demux->tsbufp)) {
-               if (count < (j=188-i)) {
+       if (demux->tsbufp) {
+               i = demux->tsbufp;
+               j = 188 - i;
+               if (count < j) {
                        memcpy(&demux->tsbuf[i], buf, count);
                        demux->tsbufp += count;
                        goto bailout;
@@ -469,13 +438,13 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 
        while (p < count) {
                if (buf[p] == 0x47) {
-                       if (count-p >= 188) {
-                               dvb_dmx_swfilter_packet(demux, buf+p);
+                       if (count - p >= 188) {
+                               dvb_dmx_swfilter_packet(demux, &buf[p]);
                                p += 188;
                        } else {
-                               i = count-p;
-                               memcpy(demux->tsbuf, buf+p, i);
-                               demux->tsbufp=i;
+                               i = count - p;
+                               memcpy(demux->tsbuf, &buf[p], i);
+                               demux->tsbufp = i;
                                goto bailout;
                        }
                } else
@@ -485,24 +454,29 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
 bailout:
        spin_unlock(&demux->lock);
 }
+
 EXPORT_SYMBOL(dvb_dmx_swfilter);
 
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
-       int p = 0,i, j;
+       int p = 0, i, j;
        u8 tmppack[188];
+
        spin_lock(&demux->lock);
 
-       if ((i = demux->tsbufp)) {
-               if (count < (j=204-i)) {
+       if (demux->tsbufp) {
+               i = demux->tsbufp;
+               j = 204 - i;
+               if (count < j) {
                        memcpy(&demux->tsbuf[i], buf, count);
                        demux->tsbufp += count;
                        goto bailout;
                }
                memcpy(&demux->tsbuf[i], buf, j);
-               if ((demux->tsbuf[0] == 0x47)|(demux->tsbuf[0]==0xB8))  {
+               if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
                        memcpy(tmppack, demux->tsbuf, 188);
-                       if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+                       if (tmppack[0] == 0xB8)
+                               tmppack[0] = 0x47;
                        dvb_dmx_swfilter_packet(demux, tmppack);
                }
                demux->tsbufp = 0;
@@ -510,16 +484,17 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
        }
 
        while (p < count) {
-               if ((buf[p] == 0x47)|(buf[p] == 0xB8)) {
-                       if (count-p >= 204) {
-                               memcpy(tmppack, buf+p, 188);
-                               if (tmppack[0] == 0xB8) tmppack[0] = 0x47;
+               if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+                       if (count - p >= 204) {
+                               memcpy(tmppack, &buf[p], 188);
+                               if (tmppack[0] == 0xB8)
+                                       tmppack[0] = 0x47;
                                dvb_dmx_swfilter_packet(demux, tmppack);
                                p += 204;
                        } else {
-                               i = count-p;
-                               memcpy(demux->tsbuf, buf+p, i);
-                               demux->tsbufp=i;
+                               i = count - p;
+                               memcpy(demux->tsbuf, &buf[p], i);
+                               demux->tsbufp = i;
                                goto bailout;
                        }
                } else {
@@ -530,14 +505,14 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 bailout:
        spin_unlock(&demux->lock);
 }
-EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 
-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;
 
-       for (i=0; i<demux->filternum; i++)
+       for (i = 0; i < demux->filternum; i++)
                if (demux->filter[i].state == DMX_STATE_FREE)
                        break;
 
@@ -549,11 +524,11 @@ static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
        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;
 
-       for (i=0; i<demux->feednum; i++)
+       for (i = 0; i < demux->feednum; i++)
                if (demux->feed[i].state == DMX_STATE_FREE)
                        break;
 
@@ -581,7 +556,7 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
        spin_lock_irq(&feed->demux->lock);
        if (dvb_demux_feed_find(feed)) {
                printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
-                               __FUNCTION__, feed->type, feed->state, feed->pid);
+                      __FUNCTION__, feed->type, feed->state, feed->pid);
                goto out;
        }
 
@@ -595,7 +570,7 @@ static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
        spin_lock_irq(&feed->demux->lock);
        if (!(dvb_demux_feed_find(feed))) {
                printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
-                               __FUNCTION__, feed->type, feed->state, feed->pid);
+                      __FUNCTION__, feed->type, feed->state, feed->pid);
                goto out;
        }
 
@@ -604,18 +579,17 @@ out:
        spin_unlock_irq(&feed->demux->lock);
 }
 
-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)
+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 circular_buffer_size, struct timespec timeout)
 {
-       struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed;
+       struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
        struct dvb_demux *demux = feed->demux;
 
        if (pid > DMX_MAX_PID)
                return -EINVAL;
 
-       if (down_interruptible (&demux->mutex))
+       if (down_interruptible(&demux->mutex))
                return -ERESTARTSYS;
 
        if (ts_type & TS_DECODER) {
@@ -638,20 +612,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
 
        feed->pid = pid;
        feed->buffer_size = circular_buffer_size;
-       feed->descramble = descramble;
        feed->timeout = timeout;
-       feed->cb_length = callback_length;
        feed->ts_type = ts_type;
        feed->pes_type = pes_type;
 
-       if (feed->descramble) {
-               up(&demux->mutex);
-               return -ENOSYS;
-       }
-
        if (feed->buffer_size) {
 #ifdef NOBUFS
-               feed->buffer=NULL;
+               feed->buffer = NULL;
 #else
                feed->buffer = vmalloc(feed->buffer_size);
                if (!feed->buffer) {
@@ -667,14 +634,13 @@ static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
        return 0;
 }
 
-
-static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* 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_feed *feed = (struct dvb_demux_feed *)ts_feed;
        struct dvb_demux *demux = feed->demux;
        int ret;
 
-       if (down_interruptible (&demux->mutex))
+       if (down_interruptible(&demux->mutex))
                return -ERESTARTSYS;
 
        if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) {
@@ -701,13 +667,13 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed)
        return 0;
 }
 
-static int dmx_ts_feed_stop_filtering(struct dmx_ts_feedts_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_feed *feed = (struct dvb_demux_feed *)ts_feed;
        struct dvb_demux *demux = feed->demux;
        int ret;
 
-       if (down_interruptible (&demux->mutex))
+       if (down_interruptible(&demux->mutex))
                return -ERESTARTSYS;
 
        if (feed->state < DMX_STATE_GO) {
@@ -731,13 +697,14 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed)
        return ret;
 }
 
-static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed,
-                            dmx_ts_cb callback)
+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;
+       struct dvb_demux *demux = (struct dvb_demux *)dmx;
        struct dvb_demux_feed *feed;
 
-       if (down_interruptible (&demux->mutex))
+       if (down_interruptible(&demux->mutex))
                return -ERESTARTSYS;
 
        if (!(feed = dvb_dmx_feed_alloc(demux))) {
@@ -760,7 +727,6 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
        (*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
        (*ts_feed)->set = dmx_ts_feed_set;
 
-
        if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
                feed->state = DMX_STATE_FREE;
                up(&demux->mutex);
@@ -776,22 +742,22 @@ static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **
        return 0;
 }
 
-static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *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;
+       struct dvb_demux *demux = (struct dvb_demux *)dmx;
+       struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
 
-       if (down_interruptible (&demux->mutex))
+       if (down_interruptible(&demux->mutex))
                return -ERESTARTSYS;
 
        if (feed->state == DMX_STATE_FREE) {
                up(&demux->mutex);
                return -EINVAL;
        }
-
 #ifndef NOBUFS
        vfree(feed->buffer);
-       feed->buffer=0;
+       feed->buffer = NULL;
 #endif
 
        feed->state = DMX_STATE_FREE;
@@ -808,19 +774,18 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_
        return 0;
 }
 
-
 /******************************************************************************
  * dmx_section_feed API calls
  ******************************************************************************/
 
-static int dmx_section_feed_allocate_filter(struct dmx_section_feedfeed,
-                                    struct dmx_section_filter** 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_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
        struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
        struct dvb_demux_filter *dvbdmxfilter;
 
-       if (down_interruptible (&dvbdemux->mutex))
+       if (down_interruptible(&dvbdemux->mutex))
                return -ERESTARTSYS;
 
        dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
@@ -844,36 +809,29 @@ static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed,
        return 0;
 }
 
-
-static int dmx_section_feed_set(struct dmx_section_feed* feed,
-                        u16 pid, size_t circular_buffer_size,
-                        int descramble, int check_crc)
+static int dmx_section_feed_set(struct dmx_section_feed *feed,
+                               u16 pid, size_t circular_buffer_size,
+                               int check_crc)
 {
-       struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) feed;
+       struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
        if (pid > 0x1fff)
                return -EINVAL;
 
-       if (down_interruptible (&dvbdmx->mutex))
+       if (down_interruptible(&dvbdmx->mutex))
                return -ERESTARTSYS;
 
        dvb_demux_feed_add(dvbdmxfeed);
 
        dvbdmxfeed->pid = pid;
        dvbdmxfeed->buffer_size = circular_buffer_size;
-       dvbdmxfeed->descramble = descramble;
-       if (dvbdmxfeed->descramble) {
-               up(&dvbdmx->mutex);
-               return -ENOSYS;
-       }
-
        dvbdmxfeed->feed.sec.check_crc = check_crc;
 
 #ifdef NOBUFS
        dvbdmxfeed->buffer = NULL;
 #else
-       dvbdmxfeed->buffer=vmalloc(dvbdmxfeed->buffer_size);
+       dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
        if (!dvbdmxfeed->buffer) {
                up(&dvbdmx->mutex);
                return -ENOMEM;
@@ -885,7 +843,6 @@ static int dmx_section_feed_set(struct dmx_section_feed* feed,
        return 0;
 }
 
-
 static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
 {
        int i;
@@ -893,12 +850,12 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
        struct dmx_section_filter *sf;
        u8 mask, mode, doneq;
 
-       if (!(f=dvbdmxfeed->filter))
+       if (!(f = dvbdmxfeed->filter))
                return;
        do {
                sf = &f->filter;
                doneq = 0;
-               for (i=0; i<DVB_DEMUX_MASK_MAX; i++) {
+               for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
                        mode = sf->filter_mode[i];
                        mask = sf->filter_mask[i];
                        f->maskandmode[i] = mask & mode;
@@ -908,14 +865,13 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
        } while ((f = f->next));
 }
 
-
 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_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
        int ret;
 
-       if (down_interruptible (&dvbdmx->mutex))
+       if (down_interruptible(&dvbdmx->mutex))
                return -ERESTARTSYS;
 
        if (feed->is_filtering) {
@@ -954,14 +910,13 @@ static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
        return 0;
 }
 
-
-static int dmx_section_feed_stop_filtering(struct dmx_section_feed* 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_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
        int ret;
 
-       if (down_interruptible (&dvbdmx->mutex))
+       if (down_interruptible(&dvbdmx->mutex))
                return -ERESTARTSYS;
 
        if (!dvbdmx->stop_feed) {
@@ -980,15 +935,14 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed)
        return ret;
 }
 
-
 static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
-                               struct dmx_section_filter* filter)
+                                          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;
+       struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f;
+       struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
        struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
-       if (down_interruptible (&dvbdmx->mutex))
+       if (down_interruptible(&dvbdmx->mutex))
                return -ERESTARTSYS;
 
        if (dvbdmxfilter->feed != dvbdmxfeed) {
@@ -1005,7 +959,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
        if (f == dvbdmxfilter) {
                dvbdmxfeed->filter = dvbdmxfilter->next;
        } else {
-               while(f->next != dvbdmxfilter)
+               while (f->next != dvbdmxfilter)
                        f = f->next;
                f->next = f->next->next;
        }
@@ -1020,10 +974,10 @@ 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;
+       struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
        struct dvb_demux_feed *dvbdmxfeed;
 
-       if (down_interruptible (&dvbdmx->mutex))
+       if (down_interruptible(&dvbdmx->mutex))
                return -ERESTARTSYS;
 
        if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
@@ -1041,7 +995,7 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
        dvbdmxfeed->filter = NULL;
        dvbdmxfeed->buffer = NULL;
 
-       (*feed)=&dvbdmxfeed->feed.sec;
+       (*feed) = &dvbdmxfeed->feed.sec;
        (*feed)->is_filtering = 0;
        (*feed)->parent = demux;
        (*feed)->priv = NULL;
@@ -1059,21 +1013,21 @@ static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
 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;
+       struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+       struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
 
-       if (down_interruptible (&dvbdmx->mutex))
+       if (down_interruptible(&dvbdmx->mutex))
                return -ERESTARTSYS;
 
-       if (dvbdmxfeed->state==DMX_STATE_FREE) {
+       if (dvbdmxfeed->state == DMX_STATE_FREE) {
                up(&dvbdmx->mutex);
                return -EINVAL;
        }
 #ifndef NOBUFS
        vfree(dvbdmxfeed->buffer);
-       dvbdmxfeed->buffer=0;
+       dvbdmxfeed->buffer = NULL;
 #endif
-       dvbdmxfeed->state=DMX_STATE_FREE;
+       dvbdmxfeed->state = DMX_STATE_FREE;
 
        dvb_demux_feed_del(dvbdmxfeed);
 
@@ -1083,14 +1037,13 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
        return 0;
 }
 
-
 /******************************************************************************
  * dvb_demux kernel data API calls
  ******************************************************************************/
 
 static int dvbdmx_open(struct dmx_demux *demux)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
        if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
                return -EUSERS;
@@ -1099,10 +1052,9 @@ static int dvbdmx_open(struct dmx_demux *demux)
        return 0;
 }
 
-
 static int dvbdmx_close(struct dmx_demux *demux)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
        if (dvbdemux->users == 0)
                return -ENODEV;
@@ -1112,15 +1064,14 @@ static int dvbdmx_close(struct dmx_demux *demux)
        return 0;
 }
 
-
 static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
 {
-       struct dvb_demux *dvbdemux=(struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
        if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
                return -EINVAL;
 
-       if (down_interruptible (&dvbdemux->mutex))
+       if (down_interruptible(&dvbdemux->mutex))
                return -ERESTARTSYS;
        dvb_dmx_swfilter(dvbdemux, buf, count);
        up(&dvbdemux->mutex);
@@ -1130,10 +1081,10 @@ static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
        return count;
 }
 
-
-static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_add_frontend(struct dmx_demux *demux,
+                              struct dmx_frontend *frontend)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
        struct list_head *head = &dvbdemux->frontend_list;
 
        list_add(&(frontend->connectivity_list), head);
@@ -1141,13 +1092,13 @@ static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *fro
        return 0;
 }
 
-
-static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_remove_frontend(struct dmx_demux *demux,
+                                 struct dmx_frontend *frontend)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
        struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
 
-       list_for_each_safe (pos, n, head) {
+       list_for_each_safe(pos, n, head) {
                if (DMX_FE_ENTRY(pos) == frontend) {
                        list_del(pos);
                        return 0;
@@ -1157,25 +1108,25 @@ static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *
        return -ENODEV;
 }
 
-
-static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux)
+static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
        if (list_empty(&dvbdemux->frontend_list))
                return NULL;
+
        return &dvbdemux->frontend_list;
 }
 
-
-static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend)
+static int dvbdmx_connect_frontend(struct dmx_demux *demux,
+                                  struct dmx_frontend *frontend)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
        if (demux->frontend)
                return -EINVAL;
 
-       if (down_interruptible (&dvbdemux->mutex))
+       if (down_interruptible(&dvbdemux->mutex))
                return -ERESTARTSYS;
 
        demux->frontend = frontend;
@@ -1183,12 +1134,11 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend
        return 0;
 }
 
-
 static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
-       if (down_interruptible (&dvbdemux->mutex))
+       if (down_interruptible(&dvbdemux->mutex))
                return -ERESTARTSYS;
 
        demux->frontend = NULL;
@@ -1196,44 +1146,42 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
        return 0;
 }
 
-
-static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
+static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
 {
-       struct dvb_demux *dvbdemux = (struct dvb_demux *) demux;
+       struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
 
-       memcpy(pids, dvbdemux->pids, 5*sizeof(u16));
+       memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
        return 0;
 }
 
-
 int dvb_dmx_init(struct dvb_demux *dvbdemux)
 {
-       int i, err;
+       int i;
        struct dmx_demux *dmx = &dvbdemux->dmx;
 
        dvbdemux->users = 0;
-       dvbdemux->filter = vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter));
+       dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
 
        if (!dvbdemux->filter)
                return -ENOMEM;
 
-       dvbdemux->feed = vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed));
+       dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
        if (!dvbdemux->feed) {
                vfree(dvbdemux->filter);
                return -ENOMEM;
        }
-       for (i=0; i<dvbdemux->filternum; i++) {
+       for (i = 0; i < dvbdemux->filternum; i++) {
                dvbdemux->filter[i].state = DMX_STATE_FREE;
                dvbdemux->filter[i].index = i;
        }
-       for (i=0; i<dvbdemux->feednum; i++) {
+       for (i = 0; i < dvbdemux->feednum; i++) {
                dvbdemux->feed[i].state = DMX_STATE_FREE;
                dvbdemux->feed[i].index = i;
        }
-       dvbdemux->frontend_list.next=
-         dvbdemux->frontend_list.prev=
-           &dvbdemux->frontend_list;
-       for (i=0; i<DMX_TS_PES_OTHER; i++) {
+
+       INIT_LIST_HEAD(&dvbdemux->frontend_list);
+
+       for (i = 0; i < DMX_TS_PES_OTHER; i++) {
                dvbdemux->pesfilter[i] = NULL;
                dvbdemux->pids[i] = 0xffff;
        }
@@ -1247,12 +1195,11 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
        if (!dvbdemux->check_crc32)
                dvbdemux->check_crc32 = dvb_dmx_crc32;
 
-        if (!dvbdemux->memcopy)
-                dvbdemux->memcopy = dvb_dmx_memcopy;
+       if (!dvbdemux->memcopy)
+               dvbdemux->memcopy = dvb_dmx_memcopy;
 
        dmx->frontend = NULL;
-       dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list;
-       dmx->priv = (void *) dvbdemux;
+       dmx->priv = dvbdemux;
        dmx->open = dvbdmx_open;
        dmx->close = dvbdmx_close;
        dmx->write = dvbdmx_write;
@@ -1261,9 +1208,6 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
        dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
        dmx->release_section_feed = dvbdmx_release_section_feed;
 
-       dmx->descramble_mac_address = NULL;
-       dmx->descramble_section_payload = NULL;
-
        dmx->add_frontend = dvbdmx_add_frontend;
        dmx->remove_frontend = dvbdmx_remove_frontend;
        dmx->get_frontends = dvbdmx_get_frontends;
@@ -1274,21 +1218,15 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
        sema_init(&dvbdemux->mutex, 1);
        spin_lock_init(&dvbdemux->lock);
 
-       if ((err = dmx_register_demux(dmx)) < 0)
-               return err;
-
        return 0;
 }
-EXPORT_SYMBOL(dvb_dmx_init);
 
+EXPORT_SYMBOL(dvb_dmx_init);
 
-int dvb_dmx_release(struct dvb_demux *dvbdemux)
+void dvb_dmx_release(struct dvb_demux *dvbdemux)
 {
-       struct dmx_demux *dmx = &dvbdemux->dmx;
-
-       dmx_unregister_demux(dmx);
        vfree(dvbdemux->filter);
        vfree(dvbdemux->feed);
-       return 0;
 }
+
 EXPORT_SYMBOL(dvb_dmx_release);
index c09beb3916225066263db57a198500f5b03aa997..0cc888339d52e0894effd9e227756bc340057165 100644 (file)
@@ -20,7 +20,6 @@
  *
  */
 
-
 #ifndef _DVB_DEMUX_H_
 #define _DVB_DEMUX_H_
 
 #define DVB_DEMUX_MASK_MAX 18
 
 struct dvb_demux_filter {
-        struct dmx_section_filter filter;
-        u8 maskandmode    [DMX_MAX_FILTER_SIZE];
-        u8 maskandnotmode [DMX_MAX_FILTER_SIZE];
+       struct dmx_section_filter filter;
+       u8 maskandmode[DMX_MAX_FILTER_SIZE];
+       u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
        int doneq;
 
-        struct dvb_demux_filter *next;
-        struct dvb_demux_feed *feed;
-        int index;
-        int state;
-        int type;
-       int pesto;
-
-        u16 handle;
-        u16 hw_handle;
-        struct timer_list timer;
-       int ts_state;
-};
+       struct dvb_demux_filter *next;
+       struct dvb_demux_feed *feed;
+       int index;
+       int state;
+       int type;
 
+       u16 hw_handle;
+       struct timer_list timer;
+};
 
 #define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
 
 struct dvb_demux_feed {
-        union {
-               struct dmx_ts_feed ts;
-               struct dmx_section_feed sec;
+       union {
+               struct dmx_ts_feed ts;
+               struct dmx_section_feed sec;
        } feed;
 
-        union {
-               dmx_ts_cb ts;
-               dmx_section_cb sec;
+       union {
+               dmx_ts_cb ts;
+               dmx_section_cb sec;
        } cb;
 
-        struct dvb_demux *demux;
+       struct dvb_demux *demux;
        void *priv;
-        int type;
-        int state;
-        u16 pid;
-        u8 *buffer;
-        int buffer_size;
-        int descramble;
+       int type;
+       int state;
+       u16 pid;
+       u8 *buffer;
+       int buffer_size;
 
-        struct timespec timeout;
-        struct dvb_demux_filter *filter;
-        int cb_length;
+       struct timespec timeout;
+       struct dvb_demux_filter *filter;
 
-        int ts_type;
-        enum dmx_ts_pes pes_type;
+       int ts_type;
+       enum dmx_ts_pes pes_type;
 
-        int cc;
-        int pusi_seen; /* prevents feeding of garbage from previous section */
+       int cc;
+       int pusi_seen;          /* prevents feeding of garbage from previous section */
 
-        u16 peslen;
+       u16 peslen;
 
        struct list_head list_head;
-               int index; /* a unique index for each feed (can be used as hardware pid filter index) */
+       unsigned int index;     /* a unique index for each feed (can be used as hardware pid filter index) */
 };
 
 struct dvb_demux {
-        struct dmx_demux dmx;
-        void *priv;
-        int filternum;
-        int feednum;
-        int (*start_feed) (struct dvb_demux_feed *feed);
-        int (*stop_feed) (struct dvb_demux_feed *feed);
-        int (*write_to_decoder) (struct dvb_demux_feed *feed,
+       struct dmx_demux dmx;
+       void *priv;
+       int filternum;
+       int feednum;
+       int (*start_feed)(struct dvb_demux_feed *feed);
+       int (*stop_feed)(struct dvb_demux_feed *feed);
+       int (*write_to_decoder)(struct dvb_demux_feed *feed,
                                 const u8 *buf, size_t len);
-       u32 (*check_crc32) (struct dvb_demux_feed *feed,
+       u32 (*check_crc32)(struct dvb_demux_feed *feed,
                            const u8 *buf, size_t len);
-       void (*memcopy) (struct dvb_demux_feed *feed, u8 *dst,
+       void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
                         const u8 *src, size_t len);
 
-        int users;
+       int users;
 #define MAX_DVB_DEMUX_USERS 10
-        struct dvb_demux_filter *filter;
-        struct dvb_demux_feed *feed;
+       struct dvb_demux_filter *filter;
+       struct dvb_demux_feed *feed;
 
-        struct list_head frontend_list;
+       struct list_head frontend_list;
 
-        struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
-        u16 pids[DMX_TS_PES_OTHER];
-        int playing;
-        int recording;
+       struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
+       u16 pids[DMX_TS_PES_OTHER];
+       int playing;
+       int recording;
 
 #define DMX_MAX_PID 0x2000
        struct list_head feed_list;
-        u8 tsbuf[204];
-        int tsbufp;
+       u8 tsbuf[204];
+       int tsbufp;
 
        struct semaphore mutex;
        spinlock_t lock;
 };
 
-
 int dvb_dmx_init(struct dvb_demux *dvbdemux);
-int dvb_dmx_release(struct dvb_demux *dvbdemux);
-void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count);
+void dvb_dmx_release(struct dvb_demux *dvbdemux);
+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);
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count);
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
+                         size_t count);
 
 #endif /* _DVB_DEMUX_H_ */
index 6a968c346a367d9595bfbfc979b8203aebc3051e..87935490bfb2f1e4deb34c0bea36ff5de3cf4c7c 100644 (file)
@@ -62,7 +62,6 @@
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/crc32.h>
-#include <linux/version.h>
 
 #include "dvb_demux.h"
 #include "dvb_net.h"
@@ -171,11 +170,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
 
        skb->mac.raw=skb->data;
        skb_pull(skb,dev->hard_header_len);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8)
-       eth = skb->mac.ethernet;
-#else
        eth = eth_hdr(skb);
-#endif
 
        if (*eth->h_dest & 1) {
                if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
@@ -908,7 +903,7 @@ static int dvb_net_feed_start(struct net_device *dev)
                        return ret;
                }
 
-               ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);
+               ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
 
                if (ret<0) {
                        printk("%s: could not set section feed\n", dev->name);
@@ -960,9 +955,7 @@ static int dvb_net_feed_start(struct net_device *dev)
                priv->tsfeed->priv = (void *)dev;
                ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
                                        TS_PACKET, DMX_TS_PES_OTHER,
-                                       188 * 100, /* nr. of bytes delivered per callback */
                                        32768,     /* circular buffer size */
-                                       0,         /* descramble */
                                        timeout);
 
                if (ret < 0) {
index 612e5b087b1c1208b5a517a12b7ad1fa8728d348..54e2b29076b12efc981d328cf09d51dce144ccd7 100644 (file)
@@ -93,13 +93,30 @@ config DVB_USB_DIGITV
          Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
 
 config DVB_USB_VP7045
-       tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
+       tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
        depends on DVB_USB
        help
          Say Y here to support the
+
            TwinhanDTV Alpha (stick) (VP-7045),
-               TwinhanDTV MagicBox II (VP-7046) and
-               DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
+               TwinhanDTV MagicBox II (VP-7046),
+               DigitalNow TinyUSB 2 DVB-t,
+               DigitalRise USB 2.0 Ter (Beetle) and
+               TYPHOON DVB-T USB DRIVE
+
+         DVB-T USB2.0 receivers.
+
+config DVB_USB_VP702X
+       tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
+       depends on DVB_USB
+       help
+         Say Y here to support the
+
+           TwinhanDTV StarBox,
+               DigitalRise USB Starbox and
+               TYPHOON DVB-S USB 2.0 BOX
+
+         DVB-S USB2.0 receivers.
 
 config DVB_USB_NOVA_T_USB2
        tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
index 746d87ed6f3280248d96179a3a0b41c8dd280e68..2dc9aad9681e36825043ce1d0dd8628139fdaa3a 100644 (file)
@@ -4,6 +4,9 @@ obj-$(CONFIG_DVB_USB) += dvb-usb.o
 dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
 obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
 
+dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
+obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
+
 dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
 obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
 
index f2fcc2f1f846114391ae66ddffebd89dec5027d8..e55322ef76b393280d39ed542a959bc71debdb0f 100644 (file)
@@ -90,7 +90,7 @@ static struct dvb_usb_properties a800_properties;
 static int a800_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
+       return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE,NULL);
 }
 
 /* do not change the order of the ID table */
index 9e96a188f1e9a7b0996c44d64eb6d90aa10cdc54..3fe383f4bb4cea3d69a69bc191a4356c6bb0d979 100644 (file)
@@ -48,35 +48,26 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
        return 0;
 }
 
-/* I2C */
-static void cxusb_set_i2c_path(struct dvb_usb_device *d, enum cxusb_i2c_pathes path)
+/* GPIO */
+static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
 {
        struct cxusb_state *st = d->priv;
        u8 o[2],i;
 
-       if (path == st->cur_i2c_path)
+       if (st->gpio_write_state[GPIO_TUNER] == onoff)
                return;
 
-       o[0] = IOCTL_SET_I2C_PATH;
-       switch (path) {
-               case PATH_CX22702:
-                       o[1] = 0;
-                       break;
-               case PATH_TUNER_OTHER:
-                       o[1] = 1;
-                       break;
-               default:
-                       err("unkown i2c path");
-                       return;
-       }
-       cxusb_ctrl_msg(d,CMD_IOCTL,o,2,&i,1);
+       o[0] = GPIO_TUNER;
+       o[1] = onoff;
+       cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
 
        if (i != 0x01)
-               deb_info("i2c_path setting failed.\n");
+               deb_info("gpio_write failed.\n");
 
-       st->cur_i2c_path = path;
+       st->gpio_write_state[GPIO_TUNER] = onoff;
 }
 
+/* I2C */
 static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
@@ -92,10 +83,10 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
 
                switch (msg[i].addr) {
                        case 0x63:
-                               cxusb_set_i2c_path(d,PATH_CX22702);
+                               cxusb_gpio_tuner(d,0);
                                break;
                        default:
-                               cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
+                               cxusb_gpio_tuner(d,1);
                                break;
                }
 
@@ -147,16 +138,20 @@ static struct i2c_algorithm cxusb_i2c_algo = {
 
 static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       return 0;
+       u8 b = 0;
+       if (onoff)
+               return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
+       else
+               return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
 }
 
 static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
 {
        u8 buf[2] = { 0x03, 0x00 };
        if (onoff)
-               cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
+               cxusb_ctrl_msg(d,CMD_STREAMING_ON, buf, 2, NULL, 0);
        else
-               cxusb_ctrl_msg(d,0x37, NULL, 0, NULL, 0);
+               cxusb_ctrl_msg(d,CMD_STREAMING_OFF, NULL, 0, NULL, 0);
 
        return 0;
 }
@@ -182,22 +177,11 @@ static int cxusb_tuner_attach(struct dvb_usb_device *d)
 
 static int cxusb_frontend_attach(struct dvb_usb_device *d)
 {
-       u8 buf[2] = { 0x03, 0x00 };
-       u8 b = 0;
-
-       if (usb_set_interface(d->udev,0,0) < 0)
-               err("set interface to alts=0 failed");
-
-       cxusb_ctrl_msg(d,0xde,&b,0,NULL,0);
-       cxusb_set_i2c_path(d,PATH_TUNER_OTHER);
-       cxusb_ctrl_msg(d,CMD_POWER_OFF, NULL, 0, &b, 1);
-
+       u8 b;
        if (usb_set_interface(d->udev,0,6) < 0)
                err("set interface failed");
 
-       cxusb_ctrl_msg(d,0x36, buf, 2, NULL, 0);
-       cxusb_set_i2c_path(d,PATH_CX22702);
-       cxusb_ctrl_msg(d,CMD_POWER_ON, NULL, 0, &b, 1);
+       cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
 
        if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
                return 0;
@@ -211,7 +195,7 @@ static struct dvb_usb_properties cxusb_properties;
 static int cxusb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE);
+       return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE,NULL);
 }
 
 static struct usb_device_id cxusb_table [] = {
@@ -237,14 +221,12 @@ static struct dvb_usb_properties cxusb_properties = {
        .generic_bulk_ctrl_endpoint = 0x01,
        /* parameter for the MPEG2-data transfer */
        .urb = {
-               .type = DVB_USB_ISOC,
+               .type = DVB_USB_BULK,
                .count = 5,
                .endpoint = 0x02,
                .u = {
-                       .isoc = {
-                               .framesperurb = 32,
-                               .framesize = 940,
-                               .interval = 5,
+                       .bulk = {
+                               .buffersize = 8192,
                        }
                }
        },
index 1d79016e319521aa20d87c303329a334840c3938..135c2a81f5817f5685745d22966483737afd7190 100644 (file)
@@ -1,30 +1,31 @@
 #ifndef _DVB_USB_CXUSB_H_
 #define _DVB_USB_CXUSB_H_
 
-#define DVB_USB_LOG_PREFIX "digitv"
+#define DVB_USB_LOG_PREFIX "cxusb"
 #include "dvb-usb.h"
 
 extern int dvb_usb_cxusb_debug;
 #define deb_info(args...)   dprintk(dvb_usb_cxusb_debug,0x01,args)
 
 /* usb commands - some of it are guesses, don't have a reference yet */
-#define CMD_I2C_WRITE    0x08
-#define CMD_I2C_READ     0x09
+#define CMD_I2C_WRITE     0x08
+#define CMD_I2C_READ      0x09
 
-#define CMD_IOCTL        0x0e
-#define    IOCTL_SET_I2C_PATH 0x02
+#define CMD_GPIO_READ     0x0d
+#define CMD_GPIO_WRITE    0x0e
+#define     GPIO_TUNER         0x02
 
-#define CMD_POWER_OFF    0x50
-#define CMD_POWER_ON     0x51
+#define CMD_POWER_OFF     0xdc
+#define CMD_POWER_ON      0xde
 
-enum cxusb_i2c_pathes {
-       PATH_UNDEF       = 0x00,
-       PATH_CX22702     = 0x01,
-       PATH_TUNER_OTHER = 0x02,
-};
+#define CMD_STREAMING_ON  0x36
+#define CMD_STREAMING_OFF 0x37
+
+#define CMD_ANALOG        0x50
+#define CMD_DIGITAL       0x51
 
 struct cxusb_state {
-       enum cxusb_i2c_pathes cur_i2c_path;
+       u8 gpio_write_state[3];
 };
 
 #endif
index 828b5182e16c31b62bbbd7f1b906225a511d2258..0058505634a0be54a8209dea0fcf01945abba2ad 100644 (file)
@@ -86,9 +86,9 @@ static struct dvb_usb_properties dibusb2_0b_properties;
 static int dibusb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
-               dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 ||
-               dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
+       if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 ||
+               dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 ||
+               dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0)
                return 0;
 
        return -EINVAL;
@@ -126,10 +126,12 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
 /* 25 */       { USB_DEVICE(USB_VID_KYE,                       USB_PID_KYE_DVB_T_COLD) },
 /* 26 */       { USB_DEVICE(USB_VID_KYE,                       USB_PID_KYE_DVB_T_WARM) },
 
+/* 27 */       { USB_DEVICE(USB_VID_KWORLD,            USB_PID_KWORLD_VSTREAM_COLD) },
+
 // #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
 
 #ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
-/* 27 */       { USB_DEVICE(USB_VID_ANCHOR,            USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+/* 28 */       { USB_DEVICE(USB_VID_ANCHOR,            USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
 #endif
                        { }             /* Terminating entry */
 };
@@ -262,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
                },
 #ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
                {       "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
-                       { &dibusb_dib3000mb_table[27], NULL },
+                       { &dibusb_dib3000mb_table[28], NULL },
                        { NULL },
                },
 #endif
@@ -306,12 +308,16 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
                }
        },
 
-       .num_device_descs = 1,
+       .num_device_descs = 2,
        .devices = {
-               {       "KWorld/ADSTech Instant DVB-T USB 2.0",
+               {       "KWorld/ADSTech Instant DVB-T USB2.0",
                        { &dibusb_dib3000mb_table[23], NULL },
                        { &dibusb_dib3000mb_table[24], NULL },
                },
+               {       "KWorld Xpert DVB-T USB2.0",
+                       { &dibusb_dib3000mb_table[27], NULL },
+                       { NULL }
+               },
        }
 };
 
index e9dac430f37da036079d2ea50a77ae8113ad63eb..6a0912eab396085cd99b30064d949362fca6b2b8 100644 (file)
@@ -20,7 +20,7 @@ static struct dvb_usb_properties dibusb_mc_properties;
 static int dibusb_mc_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
+       return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE,NULL);
 }
 
 /* do not change the order of the ID table */
index f70e0be0920aee35ef9b1cdc075a4331fc3e7511..74545f82eff1d2df2aca6e02f2577e8c9372827a 100644 (file)
@@ -111,31 +111,28 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
 }
 
 static struct mt352_config digitv_mt352_config = {
-       .demod_address = 0x0, /* ignored by the digitv anyway */
        .demod_init = digitv_mt352_demod_init,
        .pll_set = dvb_usb_pll_set,
 };
 
-static struct nxt6000_config digitv_nxt6000_config = {
-       .demod_address = 0x0, /* ignored by the digitv anyway */
-       .clock_inversion = 0x0,
+static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+       struct dvb_usb_device *d = fe->dvb->priv;
+       u8 b[5];
+       dvb_usb_pll_set(fe,fep,b);
+       return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
+}
 
-       .pll_init = NULL,
-       .pll_set = NULL,
+static struct nxt6000_config digitv_nxt6000_config = {
+       .clock_inversion = 1,
+       .pll_set = digitv_nxt6000_pll_set,
 };
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
-       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
+               (d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
                return 0;
-       if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
-
-               warn("nxt6000 support is not done yet, in fact you are one of the first "
-                               "person who wants to use this device in Linux. Please report to "
-                               "linux-dvb@linuxtv.org");
-
-               return 0;
-       }
        return -EIO;
 }
 
@@ -173,7 +170,18 @@ static struct dvb_usb_properties digitv_properties;
 static int digitv_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
+       struct dvb_usb_device *d;
+       int ret;
+       if ((ret = dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE,&d)) == 0) {
+               u8 b[4] = { 0 };
+
+               b[0] = 1;
+               digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
+
+               b[0] = 0;
+               digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+       }
+       return ret;
 }
 
 static struct usb_device_id digitv_table [] = {
index b032523b07bc42aaeac7116926e6a7824e7702ed..0a94ec22aeb863bc7423d8fc55882ff3daae640f 100644 (file)
@@ -18,6 +18,7 @@ struct dtt200u_fe_state {
 
        struct dvb_frontend_parameters fep;
        struct dvb_frontend frontend;
+       struct dvb_frontend_ops ops;
 };
 
 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,8 +164,9 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
        deb_info("attaching frontend dtt200u\n");
 
        state->d = d;
+       memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 
-       state->frontend.ops = &dtt200u_fe_ops;
+       state->frontend.ops = &state->ops;
        state->frontend.demodulator_priv = state;
 
        goto success;
index 47dba6e45968b9095c02f1ec709a230e69f5270e..5aa12ebab34f1cbfffee444ace0a89a4d547734e 100644 (file)
@@ -98,20 +98,19 @@ static struct dvb_usb_properties wt220u_properties;
 static int dtt200u_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE) == 0 ||
-               dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE) == 0)
+       if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
+               dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0)
                return 0;
 
        return -ENODEV;
 }
 
 static struct usb_device_id dtt200u_usb_table [] = {
-//             { USB_DEVICE(0x04b4,0x8613) },
-           { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
-           { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
-               { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD)  },
-               { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
-           { 0 },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
+       { 0 },
 };
 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
 
@@ -189,7 +188,7 @@ static struct dvb_usb_properties wt220u_properties = {
 
        .num_device_descs = 1,
        .devices = {
-               { .name = "WideView WT-220U PenType Receiver (and clones)",
+               { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
                  .cold_ids = { &dtt200u_usb_table[2], NULL },
                  .warm_ids = { &dtt200u_usb_table[3], NULL },
                },
@@ -201,9 +200,9 @@ static struct dvb_usb_properties wt220u_properties = {
 static struct usb_driver dtt200u_usb_driver = {
        .owner          = THIS_MODULE,
        .name           = "dvb_usb_dtt200u",
-       .probe          = dtt200u_usb_probe,
+       .probe          = dtt200u_usb_probe,
        .disconnect = dvb_usb_device_exit,
-       .id_table       = dtt200u_usb_table,
+       .id_table       = dtt200u_usb_table,
 };
 
 /* module stuff */
index 794d513a8480f8b758262bf807f60dc99083a971..0818996bf1507cc032fb5e9e76ec11f72fda5d93 100644 (file)
 #define USB_VID_HANFTEK                                                0x15f4
 #define USB_VID_HAUPPAUGE                                      0x2040
 #define USB_VID_HYPER_PALTEK                           0x1025
+#define USB_VID_KWORLD                                         0xeb2a
 #define USB_VID_KYE                                                    0x0458
 #define USB_VID_MEDION                                         0x1660
+#define USB_VID_PINNACLE                                       0x2304
 #define USB_VID_VISIONPLUS                                     0x13d3
 #define USB_VID_TWINHAN                                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC                      0x05d8
 #define USB_PID_KWORLD_VSTREAM_WARM                    0x17df
 #define USB_PID_TWINHAN_VP7041_COLD                    0x3201
 #define USB_PID_TWINHAN_VP7041_WARM                    0x3202
+#define USB_PID_TWINHAN_VP7020_COLD                    0x3203
+#define USB_PID_TWINHAN_VP7020_WARM                    0x3204
 #define USB_PID_TWINHAN_VP7045_COLD                    0x3205
 #define USB_PID_TWINHAN_VP7045_WARM                    0x3206
-#define USB_PID_DNTV_TINYUSB2_COLD                     0x3223
-#define USB_PID_DNTV_TINYUSB2_WARM                     0x3224
 #define USB_PID_TWINHAN_VP7021_COLD                    0x3207
 #define USB_PID_TWINHAN_VP7021_WARM                    0x3208
+#define USB_PID_DNTV_TINYUSB2_COLD                     0x3223
+#define USB_PID_DNTV_TINYUSB2_WARM                     0x3224
 #define USB_PID_ULTIMA_TVBOX_COLD                      0x8105
 #define USB_PID_ULTIMA_TVBOX_WARM                      0x8106
 #define USB_PID_ULTIMA_TVBOX_AN2235_COLD       0x8107
@@ -85,5 +89,7 @@
 #define USB_PID_MEDION_MD95700                         0x0932
 #define USB_PID_KYE_DVB_T_COLD                         0x701e
 #define USB_PID_KYE_DVB_T_WARM                         0x701f
+#define USB_PID_PCTV_200E                                      0x020e
+#define USB_PID_PCTV_400E                                      0x020f
 
 #endif
index 65f0c095abc9184f5ec9e08cb7878afb7999d985..a902059812a2fdc7baf6a8a1de6bc9888fb7253f 100644 (file)
@@ -128,7 +128,9 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
 /*
  * USB
  */
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
+
+int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
+               *props, struct module *owner,struct dvb_usb_device **du)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct dvb_usb_device *d = NULL;
@@ -170,6 +172,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *p
 
                usb_set_intfdata(intf, d);
 
+               if (du != NULL)
+                       *du = d;
+
                ret = dvb_usb_init(d);
        }
 
@@ -196,19 +201,6 @@ void dvb_usb_device_exit(struct usb_interface *intf)
 }
 EXPORT_SYMBOL(dvb_usb_device_exit);
 
-/* module stuff */
-static int __init dvb_usb_module_init(void)
-{
-       return 0;
-}
-
-static void __exit dvb_usb_module_exit(void)
-{
-}
-
-module_init (dvb_usb_module_init);
-module_exit (dvb_usb_module_exit);
-
 MODULE_VERSION("0.3");
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
 MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
index a80567caf508aab80da113d31cfb495dc9d72997..0e4f1035b0dd56535407e20417e738fd3162983b 100644 (file)
@@ -127,7 +127,7 @@ struct dvb_usb_device;
  *  helper functions.
  *
  * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
- *  Currently only BULK is implemented
+ *  (BULK or ISOC)
  *
  * @num_device_descs: number of struct dvb_usb_device_description in @devices
  * @devices: array of struct dvb_usb_device_description compatibles with these
@@ -310,7 +310,7 @@ struct dvb_usb_device {
        void *priv;
 };
 
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
+extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *, struct dvb_usb_device **);
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */
index 258a92bfbcc79d354a6ffaaeb8e09be826890c2f..1841a66427bfe550c7ef7d3646b487e24f2c01ce 100644 (file)
@@ -144,7 +144,7 @@ static struct dvb_usb_properties nova_t_properties;
 static int nova_t_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
+       return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE,NULL);
 }
 
 /* do not change the order of the ID table */
index 2112ac3cf5e2c35a7059d4fa00594ff397795aba..6fd67657c2693a277567aa95cdd9fee70514b26a 100644 (file)
@@ -77,7 +77,7 @@ static struct dvb_usb_properties umt_properties;
 static int umt_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
+       if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE,NULL) == 0)
                return 0;
        return -EINVAL;
 }
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
new file mode 100644 (file)
index 0000000..f20d8db
--- /dev/null
@@ -0,0 +1,339 @@
+/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
+ * DVB-S receiver.
+ *
+ * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
+ *                    Metzler Brothers Systementwicklung GbR
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * This file can be removed soon, after the DST-driver is rewritten to provice
+ * the frontend-controlling separately.
+ *
+ *     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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ *
+ */
+#include "vp702x.h"
+
+struct vp702x_fe_state {
+       struct dvb_frontend fe;
+       struct dvb_usb_device *d;
+
+       fe_sec_voltage_t voltage;
+       fe_sec_tone_mode_t tone_mode;
+
+       u8 lnb_buf[8];
+
+       u8 lock;
+       u8 sig;
+       u8 snr;
+
+       unsigned long next_status_check;
+       unsigned long status_check_interval;
+};
+
+static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
+{
+       u8 buf[10];
+       if (time_after(jiffies,st->next_status_check)) {
+               vp702x_usb_in_op(st->d,READ_STATUS,0,0,buf,10);
+
+               st->lock = buf[4];
+               vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x11,0,&st->snr,1);
+               vp702x_usb_in_op(st->d,READ_TUNER_REG_REQ,0x15,0,&st->sig,1);
+
+               st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+       }
+       return 0;
+}
+
+static u8 vp702x_chksum(u8 *buf,int f, int count)
+{
+       u8 s = 0;
+       int i;
+       for (i = f; i < f+count; i++)
+               s += buf[i];
+       return ~s+1;
+}
+
+static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       vp702x_fe_refresh_state(st);
+       deb_fe("%s\n",__FUNCTION__);
+
+       if (st->lock == 0)
+               *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+       else
+               *status = 0;
+
+       deb_fe("real state: %x\n",*status);
+       *status = 0x1f;
+
+       if (*status & FE_HAS_LOCK)
+               st->status_check_interval = 1000;
+       else
+               st->status_check_interval = 250;
+       return 0;
+}
+
+/* not supported by this Frontend */
+static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       vp702x_fe_refresh_state(st);
+       *ber = 0;
+       return 0;
+}
+
+/* not supported by this Frontend */
+static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       vp702x_fe_refresh_state(st);
+       *unc = 0;
+       return 0;
+}
+
+static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       vp702x_fe_refresh_state(st);
+
+       *strength = (st->sig << 8) | st->sig;
+       return 0;
+}
+
+static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+       u8 _snr;
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       vp702x_fe_refresh_state(st);
+
+       _snr = (st->snr & 0x1f) * 0xff / 0x1f;
+       *snr = (_snr << 8) | _snr;
+       return 0;
+}
+
+static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       deb_fe("%s\n",__FUNCTION__);
+       tune->min_delay_ms = 2000;
+       return 0;
+}
+
+static int vp702x_fe_set_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       u32 freq = fep->frequency/1000;
+       /*CalFrequency*/
+/*     u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
+       u64 sr;
+       u8 cmd[8] = { 0 },ibuf[10];
+
+       cmd[0] = (freq >> 8) & 0x7f;
+       cmd[1] =  freq       & 0xff;
+       cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
+
+       sr = (u64) (fep->u.qpsk.symbol_rate/1000) << 20;
+       do_div(sr,88000);
+       cmd[3] = (sr >> 12) & 0xff;
+       cmd[4] = (sr >> 4)  & 0xff;
+       cmd[5] = (sr << 4)  & 0xf0;
+
+       deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %Lu (%Lx)\n",
+                       fep->frequency,freq,freq, fep->u.qpsk.symbol_rate, sr, sr);
+
+/*     if (fep->inversion == INVERSION_ON)
+               cmd[6] |= 0x80; */
+
+       if (st->voltage == SEC_VOLTAGE_18)
+               cmd[6] |= 0x40;
+
+/*     if (fep->u.qpsk.symbol_rate > 8000000)
+               cmd[6] |= 0x20;
+
+       if (fep->frequency < 1531000)
+               cmd[6] |= 0x04;
+
+       if (st->tone_mode == SEC_TONE_ON)
+               cmd[6] |= 0x01;*/
+
+       cmd[7] = vp702x_chksum(cmd,0,7);
+
+       st->status_check_interval = 250;
+       st->next_status_check = jiffies;
+
+       vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
+       msleep(30);
+       vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+
+       if (ibuf[2] == 0 && ibuf[3] == 0)
+               deb_fe("tuning failed.\n");
+       else
+               deb_fe("tuning succeeded.\n");
+
+       return 0;
+}
+
+static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       deb_fe("%s\n",__FUNCTION__);
+       return 0;
+}
+
+static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
+                                   struct dvb_diseqc_master_cmd *m)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       u8 cmd[8],ibuf[10];
+       memset(cmd,0,8);
+
+       deb_fe("%s\n",__FUNCTION__);
+
+       if (m->msg_len > 4)
+               return -EINVAL;
+
+       cmd[1] = SET_DISEQC_CMD;
+       cmd[2] = m->msg_len;
+       memcpy(&cmd[3], m->msg, m->msg_len);
+       cmd[7] = vp702x_chksum(cmd,0,7);
+
+       vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+
+       if (ibuf[2] == 0 && ibuf[3] == 0)
+               deb_fe("diseqc cmd failed.\n");
+       else
+               deb_fe("diseqc cmd succeeded.\n");
+
+       return 0;
+}
+
+static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+       deb_fe("%s\n",__FUNCTION__);
+       return 0;
+}
+
+static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       u8 ibuf[10];
+       deb_fe("%s\n",__FUNCTION__);
+
+       st->tone_mode = tone;
+
+       if (tone == SEC_TONE_ON)
+               st->lnb_buf[2] = 0x02;
+       else
+               st->lnb_buf[2] = 0x00;
+
+       st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+
+       vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
+       if (ibuf[2] == 0 && ibuf[3] == 0)
+               deb_fe("set_tone cmd failed.\n");
+       else
+               deb_fe("set_tone cmd succeeded.\n");
+
+       return 0;
+}
+
+static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
+               voltage)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       u8 ibuf[10];
+       deb_fe("%s\n",__FUNCTION__);
+
+       st->voltage = voltage;
+
+       if (voltage != SEC_VOLTAGE_OFF)
+               st->lnb_buf[4] = 0x01;
+       else
+               st->lnb_buf[4] = 0x00;
+
+       st->lnb_buf[7] = vp702x_chksum(st->lnb_buf,0,7);
+
+       vp702x_usb_inout_op(st->d,st->lnb_buf,8,ibuf,10,100);
+       if (ibuf[2] == 0 && ibuf[3] == 0)
+               deb_fe("set_voltage cmd failed.\n");
+       else
+               deb_fe("set_voltage cmd succeeded.\n");
+
+       return 0;
+}
+
+static void vp702x_fe_release(struct dvb_frontend* fe)
+{
+       struct vp702x_fe_state *st = fe->demodulator_priv;
+       kfree(st);
+}
+
+static struct dvb_frontend_ops vp702x_fe_ops;
+
+struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
+{
+       struct vp702x_fe_state *s = kmalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
+       if (s == NULL)
+               goto error;
+       memset(s,0,sizeof(struct vp702x_fe_state));
+
+       s->d = d;
+       s->fe.ops = &vp702x_fe_ops;
+       s->fe.demodulator_priv = s;
+
+       s->lnb_buf[1] = SET_LNB_POWER;
+       s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
+
+       goto success;
+error:
+       return NULL;
+success:
+       return &s->fe;
+}
+
+
+static struct dvb_frontend_ops vp702x_fe_ops = {
+       .info = {
+               .name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
+               .type           = FE_QPSK,
+               .frequency_min       = 950000,
+               .frequency_max       = 2150000,
+               .frequency_stepsize  = 1000,   /* kHz for QPSK frontends */
+               .frequency_tolerance = 0,
+               .symbol_rate_min     = 1000000,
+               .symbol_rate_max     = 45000000,
+               .symbol_rate_tolerance = 500,  /* ppm */
+               .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
+       },
+       .release = vp702x_fe_release,
+
+       .init = NULL,
+       .sleep = NULL,
+
+       .set_frontend = vp702x_fe_set_frontend,
+       .get_frontend = vp702x_fe_get_frontend,
+       .get_tune_settings = vp702x_fe_get_tune_settings,
+
+       .read_status = vp702x_fe_read_status,
+       .read_ber = vp702x_fe_read_ber,
+       .read_signal_strength = vp702x_fe_read_signal_strength,
+       .read_snr = vp702x_fe_read_snr,
+       .read_ucblocks = vp702x_fe_read_unc_blocks,
+
+       .diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
+       .diseqc_send_burst = vp702x_fe_send_diseqc_burst,
+       .set_tone = vp702x_fe_set_tone,
+       .set_voltage = vp702x_fe_set_voltage,
+};
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
new file mode 100644 (file)
index 0000000..de13c04
--- /dev/null
@@ -0,0 +1,290 @@
+/* DVB USB compliant Linux driver for the TwinhanDTV StarBox USB2.0 DVB-S
+ * receiver.
+ *
+ * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
+ *                    Metzler Brothers Systementwicklung GbR
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * Thanks to Twinhan who kindly provided hardware and 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "vp702x.h"
+
+/* debug */
+int dvb_usb_vp702x_debug;
+module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+struct vp702x_state {
+       u8 pid_table[17]; /* [16] controls the pid_table state */
+};
+
+/* check for mutex FIXME */
+int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+       int ret = 0,try = 0;
+
+       while (ret >= 0 && ret != blen && try < 3) {
+               ret = usb_control_msg(d->udev,
+                       usb_rcvctrlpipe(d->udev,0),
+                       req,
+                       USB_TYPE_VENDOR | USB_DIR_IN,
+                       value,index,b,blen,
+                       2000);
+               deb_info("reading number %d (ret: %d)\n",try,ret);
+               try++;
+       }
+
+       if (ret < 0 || ret != blen) {
+               warn("usb in operation failed.");
+               ret = -EIO;
+       } else
+               ret = 0;
+
+       deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+       debug_dump(b,blen,deb_xfer);
+
+       return ret;
+}
+
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+       deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+       debug_dump(b,blen,deb_xfer);
+
+       if (usb_control_msg(d->udev,
+                       usb_sndctrlpipe(d->udev,0),
+                       req,
+                       USB_TYPE_VENDOR | USB_DIR_OUT,
+                       value,index,b,blen,
+                       2000) != blen) {
+               warn("usb out operation failed.");
+               return -EIO;
+       } else
+               return 0;
+}
+
+int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
+{
+       int ret;
+
+       if ((ret = down_interruptible(&d->usb_sem)))
+               return ret;
+
+       if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0)
+               goto unlock;
+       msleep(msec);
+       ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
+
+unlock:
+       up(&d->usb_sem);
+
+       return ret;
+}
+
+int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec)
+{
+       u8 bout[olen+2];
+       u8 bin[ilen+1];
+       int ret = 0;
+
+       bout[0] = 0x00;
+       bout[1] = cmd;
+       memcpy(&bout[2],o,olen);
+
+       ret = vp702x_usb_inout_op(d, bout, olen+2, bin, ilen+1,msec);
+
+       if (ret == 0)
+               memcpy(i,&bin[1],ilen);
+
+       return ret;
+}
+
+static int vp702x_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+       struct vp702x_state *st = d->priv;
+       u8 buf[9];
+
+       if (onoff) {
+               st->pid_table[16]   |=   1 << index;
+               st->pid_table[index*2]   = (pid >> 8) & 0xff;
+               st->pid_table[index*2+1] =  pid       & 0xff;
+       } else {
+               st->pid_table[16]   &= ~(1 << index);
+               st->pid_table[index*2] = st->pid_table[index*2+1] = 0;
+       }
+
+       return vp702x_usb_inout_cmd(d,SET_PID_FILTER,st->pid_table,17,buf,9,10);
+}
+
+static int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       vp702x_usb_in_op(d,RESET_TUNER,0,0,NULL,0);
+
+       vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+       return vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+}
+
+/* keys for the enclosed remote control */
+static struct dvb_usb_rc_key vp702x_rc_keys[] = {
+       { 0x00, 0x01, KEY_1 },
+       { 0x00, 0x02, KEY_2 },
+};
+
+/* remote control stuff (does not work with my box) */
+static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       u8 key[10];
+       int i;
+
+/* remove the following return to enabled remote querying */
+       return 0;
+
+       vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
+
+       deb_rc("remote query key: %x %d\n",key[1],key[1]);
+
+       if (key[1] == 0x44) {
+               *state = REMOTE_NO_KEY_PRESSED;
+               return 0;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(vp702x_rc_keys); i++)
+               if (vp702x_rc_keys[i].custom == key[1]) {
+                       *state = REMOTE_KEY_PRESSED;
+                       *event = vp702x_rc_keys[i].event;
+                       break;
+               }
+       return 0;
+}
+
+static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
+{
+       u8 macb[9];
+       if (vp702x_usb_inout_cmd(d, GET_MAC_ADDRESS, NULL, 0, macb, 9, 10))
+               return -EIO;
+       memcpy(mac,&macb[3],6);
+       return 0;
+}
+
+static int vp702x_frontend_attach(struct dvb_usb_device *d)
+{
+       u8 buf[9] = { 0 };
+
+       if (vp702x_usb_inout_cmd(d, GET_SYSTEM_STRING, NULL, 0, buf, 9, 10))
+               return -EIO;
+
+       buf[8] = '\0';
+       info("system string: %s",&buf[1]);
+
+       d->fe = vp702x_fe_attach(d);
+       return 0;
+}
+
+static struct dvb_usb_properties vp702x_properties;
+
+static int vp702x_usb_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+
+       usb_clear_halt(udev,usb_sndctrlpipe(udev,0));
+       usb_clear_halt(udev,usb_rcvctrlpipe(udev,0));
+
+       return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id vp702x_usb_table [] = {
+           { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
+           { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_WARM) },
+           { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
+           { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
+           { 0 },
+};
+MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
+
+static struct dvb_usb_properties vp702x_properties = {
+       .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+       .pid_filter_count = 8, /* !!! */
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-vp702x-01.fw",
+
+       .pid_filter       = vp702x_pid_filter,
+       .power_ctrl       = vp702x_power_ctrl,
+       .frontend_attach  = vp702x_frontend_attach,
+       .read_mac_address = vp702x_read_mac_addr,
+
+       .rc_key_map       = vp702x_rc_keys,
+       .rc_key_map_size  = ARRAY_SIZE(vp702x_rc_keys),
+       .rc_interval      = 400,
+       .rc_query         = vp702x_rc_query,
+
+       .size_of_priv     = sizeof(struct vp702x_state),
+
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_BULK,
+               .count = 7,
+               .endpoint = 0x02,
+               .u = {
+                       .bulk = {
+                               .buffersize = 4096,
+                       }
+               }
+       },
+
+       .num_device_descs = 2,
+       .devices = {
+               { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
+                 .cold_ids = { &vp702x_usb_table[0], NULL },
+                 .warm_ids = { &vp702x_usb_table[1], NULL },
+               },
+               { .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
+                 .cold_ids = { &vp702x_usb_table[2], NULL },
+                 .warm_ids = { &vp702x_usb_table[3], NULL },
+               },
+               { 0 },
+       }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vp702x_usb_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "dvb-usb-vp702x",
+       .probe          = vp702x_usb_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table       = vp702x_usb_table,
+};
+
+/* module stuff */
+static int __init vp702x_usb_module_init(void)
+{
+       int result;
+       if ((result = usb_register(&vp702x_usb_driver))) {
+               err("usb_register failed. (%d)",result);
+               return result;
+       }
+
+       return 0;
+}
+
+static void __exit vp702x_usb_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&vp702x_usb_driver);
+}
+
+module_init(vp702x_usb_module_init);
+module_exit(vp702x_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
new file mode 100644 (file)
index 0000000..4a3e8c7
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef _DVB_USB_VP7021_H_
+#define _DVB_USB_VP7021_H_
+
+#define DVB_USB_LOG_PREFIX "vp702x"
+#include "dvb-usb.h"
+
+extern int dvb_usb_vp702x_debug;
+#define deb_info(args...) dprintk(dvb_usb_vp702x_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_vp702x_debug,0x02,args)
+#define deb_rc(args...)   dprintk(dvb_usb_vp702x_debug,0x04,args)
+#define deb_fe(args...)   dprintk(dvb_usb_vp702x_debug,0x08,args)
+
+/* commands are read and written with USB control messages */
+
+/* consecutive read/write operation */
+#define REQUEST_OUT       0xB2
+#define REQUEST_IN               0xB3
+
+/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
+ * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
+ * the returning buffer looks as follows
+ * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
+
+#define GET_TUNER_STATUS  0x05
+/* additional in buffer:
+ * 0   1   2    3              4   5   6               7       8
+ * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
+
+#define GET_SYSTEM_STRING 0x06
+/* additional in buffer:
+ * 0   1   2   3   4   5   6   7   8
+ * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
+
+#define SET_DISEQC_CMD    0x08
+/* additional out buffer:
+ * 0    1  2  3  4
+ * len  X1 X2 X3 X4
+ * additional in buffer:
+ * 0   1 2
+ * N/A 0 0   b[1] == b[2] == 0 -> success otherwise not */
+
+#define SET_LNB_POWER     0x09
+/* additional out buffer:
+ * 0    1    2
+ * 0x00 0xff 1 = on, 0 = off
+ * additional in buffer:
+ * 0   1 2
+ * N/A 0 0   b[1] == b[2] == 0 -> success otherwise not */
+
+#define GET_MAC_ADDRESS   0x0A
+/* #define GET_MAC_ADDRESS   0x0B */
+/* additional in buffer:
+ * 0   1   2            3    4    5    6    7    8
+ * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
+
+#define SET_PID_FILTER    0x11
+/* additional in buffer:
+ * 0        1        ... 14       15       16
+ * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
+
+/* request: 0xB2; i: 0; v: 0;
+ * b[0] != 0 -> tune and lock a channel
+ * 0     1     2       3      4      5      6    7
+ * freq0 freq1 divstep srate0 srate1 srate2 flag chksum
+ */
+
+
+/* one direction requests */
+#define READ_REMOTE_REQ       0xB4
+/* IN  i: 0; v: 0; b[0] == request, b[1] == key */
+
+#define READ_PID_NUMBER_REQ   0xB5
+/* IN  i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
+
+#define WRITE_EEPROM_REQ      0xB6
+/* OUT i: offset; v: value to write; no extra buffer */
+
+#define READ_EEPROM_REQ       0xB7
+/* IN  i: bufferlen; v: offset; buffer with bufferlen bytes */
+
+#define READ_STATUS           0xB8
+/* IN  i: 0; v: 0; bufferlen 10 */
+
+#define READ_TUNER_REG_REQ    0xB9
+/* IN  i: 0; v: register; b[0] = value */
+
+#define READ_FX2_REG_REQ      0xBA
+/* IN  i: offset; v: 0; b[0] = value */
+
+#define WRITE_FX2_REG_REQ     0xBB
+/* OUT i: offset; v: value to write; 1 byte extra buffer */
+
+#define SET_TUNER_POWER_REQ   0xBC
+/* IN  i: 0 = power off, 1 = power on */
+
+#define WRITE_TUNER_REG_REQ   0xBD
+/* IN  i: register, v: value to write, no extra buffer */
+
+#define RESET_TUNER           0xBE
+/* IN  i: 0, v: 0, no extra buffer */
+
+extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
+
+extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
+extern int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o, int olen, u8 *i, int ilen, int msec);
+extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+
+#endif
index 9ac95f54f9fc4e45c0e5184332b1896c8857ace3..0f57abeb6d6bc8d982f6ea16d7b91be64440de62 100644 (file)
@@ -164,7 +164,6 @@ static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int off
        return 0;
 }
 
-
 static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
 {
        return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
@@ -199,7 +198,7 @@ static struct dvb_usb_properties vp7045_properties;
 static int vp7045_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
+       return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE,NULL);
 }
 
 static struct usb_device_id vp7045_usb_table [] = {
@@ -256,9 +255,9 @@ static struct dvb_usb_properties vp7045_properties = {
 static struct usb_driver vp7045_usb_driver = {
        .owner          = THIS_MODULE,
        .name           = "dvb_usb_vp7045",
-       .probe          = vp7045_usb_probe,
+       .probe          = vp7045_usb_probe,
        .disconnect = dvb_usb_device_exit,
-       .id_table       = vp7045_usb_table,
+       .id_table       = vp7045_usb_table,
 };
 
 /* module stuff */
index 8222b88cb4868fdc8f5dd1ad2abb325c9b4e5a9b..d4b97989e3ed058b93fc926206e110906eb14a7e 100644 (file)
@@ -1,7 +1,7 @@
 /*
     cx24110 - Single Chip Satellite Channel Receiver driver module
 
-    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> based on
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
     work
     Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
 
@@ -387,8 +387,9 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
 
 static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
-       int rv, bit, i;
+       int rv, bit;
        struct cx24110_state *state = fe->demodulator_priv;
+       unsigned long timeout;
 
        if (burst == SEC_MINI_A)
                bit = 0x00;
@@ -398,12 +399,14 @@ static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
                return -EINVAL;
 
        rv = cx24110_readreg(state, 0x77);
-       cx24110_writereg(state, 0x77, rv|0x04);
+       if (!(rv & 0x04))
+               cx24110_writereg(state, 0x77, rv | 0x04);
 
        rv = cx24110_readreg(state, 0x76);
        cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
-       for (i = 500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40) ; )
-              ; /* wait for LNB ready */
+       timeout = jiffies + msecs_to_jiffies(100);
+       while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
+               ; /* wait for LNB ready */
 
        return 0;
 }
@@ -413,17 +416,22 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
 {
        int i, rv;
        struct cx24110_state *state = fe->demodulator_priv;
+       unsigned long timeout;
 
        for (i = 0; i < cmd->msg_len; i++)
                cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
 
        rv = cx24110_readreg(state, 0x77);
-       cx24110_writereg(state, 0x77, rv|0x04);
+       if (rv & 0x04) {
+               cx24110_writereg(state, 0x77, rv & ~0x04);
+               msleep(30); /* reportedly fixes switching problems */
+       }
 
        rv = cx24110_readreg(state, 0x76);
 
        cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
-       for (i=500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40);)
+       timeout = jiffies + msecs_to_jiffies(100);
+       while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
                ; /* wait for LNB ready */
 
        return 0;
index 6b663f4744e00b483ab598a8ec507d6bebc54c3f..b63ecf26421a08003ca7fced3ce278e6be5ff98b 100644 (file)
@@ -1,7 +1,7 @@
 /*
     cx24110 - Single Chip Satellite Channel Receiver driver module
 
-    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de> based on
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
     work
     Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
 
index cd434b7cf9db697370b7d46635876bd80ce58cd9..21433e1831e744f22e55cef34afdbe555eb75a92 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
index cd33705a4320b5a44ba6e8eb9158c2436e893fc4..441de665fec32aa28850d6b680fdc6a6ea638080 100644 (file)
@@ -22,7 +22,6 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
index d32dc4de9e7f1fafd539e7e9de758705760b3613..cc1bc0edd65e7d14424744985cc83c89a0b054ae 100644 (file)
@@ -462,9 +462,11 @@ static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
        struct mt352_state* state = fe->demodulator_priv;
 
-       u16 signal = ((mt352_read_register(state, AGC_GAIN_1) << 8) & 0x0f) |
-                     (mt352_read_register(state, AGC_GAIN_0));
+       /* align the 12 bit AGC gain with the most significant bits */
+       u16 signal = ((mt352_read_register(state, AGC_GAIN_1) & 0x0f) << 12) |
+               (mt352_read_register(state, AGC_GAIN_0) << 4);
 
+       /* inverse of gain is signal strength */
        *strength = ~signal;
        return 0;
 }
index 966de9853d18b7e6d9a8eadd768804603218595f..88a57b7911124cb58113afd3676d885a221992e1 100644 (file)
@@ -482,6 +482,7 @@ static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        if ((result = nxt6000_set_inversion(state, param->inversion)) < 0)
                return result;
 
+       msleep(500);
        return 0;
 }
 
@@ -525,6 +526,12 @@ static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
        return 0;
 }
 
+static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 500;
+       return 0;
+}
+
 static struct dvb_frontend_ops nxt6000_ops;
 
 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -578,6 +585,8 @@ static struct dvb_frontend_ops nxt6000_ops = {
 
        .init = nxt6000_init,
 
+       .get_tune_settings = nxt6000_fe_get_tune_settings,
+
        .set_frontend = nxt6000_set_frontend,
 
        .read_status = nxt6000_read_status,
index cc0a77c790f1add3a312e95b1ac442f3340e8955..b6d0eecc59eb0ed75c445e3872c8b6a0c8b6138e 100644 (file)
@@ -370,22 +370,19 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
                or51132_setmode(fe);
        }
 
-       /* Change only if we are actually changing the channel */
-       if (state->current_frequency != param->frequency) {
-               dvb_pll_configure(state->config->pll_desc, buf,
-                                 param->frequency, 0);
-               dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
-                       "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
-               if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
-                       printk(KERN_WARNING "or51132: set_parameters error "
-                              "writing to tuner\n");
-
-               /* Set to current mode */
-               or51132_setmode(fe);
-
-               /* Update current frequency */
-               state->current_frequency = param->frequency;
-       }
+       dvb_pll_configure(state->config->pll_desc, buf,
+                         param->frequency, 0);
+       dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
+               "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
+       if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
+               printk(KERN_WARNING "or51132: set_parameters error "
+                      "writing to tuner\n");
+
+       /* Set to current mode */
+       or51132_setmode(fe);
+
+       /* Update current frequency */
+       state->current_frequency = param->frequency;
        return 0;
 }
 
index 4f396ac8de77767070ba2e3e30790b4cf23050e8..c7fe27fd530c8037e05c4ef289ab17923d293b92 100644 (file)
@@ -48,7 +48,8 @@ struct s5h1420_state {
 };
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings);
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+                                    struct dvb_frontend_tune_settings* fesettings);
 
 
 static int debug = 0;
@@ -91,7 +92,8 @@ static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
 
        switch(voltage) {
        case SEC_VOLTAGE_13:
-               s5h1420_writereg(state, 0x3c, (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
+               s5h1420_writereg(state, 0x3c,
+                                (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
                break;
 
        case SEC_VOLTAGE_18:
@@ -112,18 +114,21 @@ static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 
        switch(tone) {
        case SEC_TONE_ON:
-               s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
+               s5h1420_writereg(state, 0x3b,
+                                (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
                break;
 
        case SEC_TONE_OFF:
-               s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+               s5h1420_writereg(state, 0x3b,
+                                (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
                break;
        }
 
        return 0;
 }
 
-static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+                                   struct dvb_diseqc_master_cmd* cmd)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
        u8 val;
@@ -131,6 +136,9 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
        unsigned long timeout;
        int result = 0;
 
+       if (cmd->msg_len > 8)
+               return -EINVAL;
+
        /* setup for DISEQC */
        val = s5h1420_readreg(state, 0x3b);
        s5h1420_writereg(state, 0x3b, 0x02);
@@ -138,16 +146,17 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
 
        /* write the DISEQC command bytes */
        for(i=0; i< cmd->msg_len; i++) {
-               s5h1420_writereg(state, 0x3c + i, cmd->msg[i]);
+               s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
        }
 
        /* kick off transmission */
-       s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | ((cmd->msg_len-1) << 4) | 0x08);
+       s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
+                                     ((cmd->msg_len-1) << 4) | 0x08);
 
        /* wait for transmission to complete */
        timeout = jiffies + ((100*HZ) / 1000);
        while(time_before(jiffies, timeout)) {
-               if (s5h1420_readreg(state, 0x3b) & 0x08)
+               if (!(s5h1420_readreg(state, 0x3b) & 0x08))
                        break;
 
                msleep(5);
@@ -161,7 +170,8 @@ static int s5h1420_send_master_cmd (struct dvb_frontend* fe, struct dvb_diseqc_m
        return result;
 }
 
-static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply)
+static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
+                                    struct dvb_diseqc_slave_reply* reply)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
        u8 val;
@@ -205,7 +215,7 @@ static int s5h1420_recv_slave_reply (struct dvb_frontend* fe, struct dvb_diseqc_
 
        /* extract data */
        for(i=0; i< length; i++) {
-               reply->msg[i] = s5h1420_readreg(state, 0x3c + i);
+               reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
        }
 
 exit:
@@ -236,7 +246,7 @@ static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicm
        s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
 
        /* wait for transmission to complete */
-       timeout = jiffies + ((20*HZ) / 1000);
+       timeout = jiffies + ((100*HZ) / 1000);
        while(time_before(jiffies, timeout)) {
                if (!(s5h1420_readreg(state, 0x3b) & 0x08))
                        break;
@@ -259,9 +269,9 @@ static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
 
        val = s5h1420_readreg(state, 0x14);
        if (val & 0x02)
-               status |=  FE_HAS_SIGNAL; // FIXME: not sure if this is right
+               status |=  FE_HAS_SIGNAL;
        if (val & 0x01)
-               status |=  FE_HAS_CARRIER; // FIXME: not sure if this is right
+               status |=  FE_HAS_CARRIER;
        val = s5h1420_readreg(state, 0x36);
        if (val & 0x01)
                status |=  FE_HAS_VITERBI;
@@ -284,8 +294,8 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
        /* determine lock state */
        *status = s5h1420_get_status_bits(state);
 
-       /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert the inversion,
-       wait a bit and check again */
+       /* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
+       the inversion, wait a bit and check again */
        if (*status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI)) {
                val = s5h1420_readreg(state, 0x32);
                if ((val & 0x07) == 0x03) {
@@ -330,6 +340,10 @@ static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
                        tmp = (tmp * 2 * 7) / 8;
                        break;
                }
+               if (tmp == 0) {
+                       printk("s5h1420: avoided division by 0\n");
+                       tmp = 1;
+               }
                tmp = state->fclk / tmp;
 
                /* set the MPEG_CLK_INTL for the calculated data rate */
@@ -368,16 +382,21 @@ static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
 
        s5h1420_writereg(state, 0x46, 0x1d);
        mdelay(25);
-       return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+       *ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+       return 0;
 }
 
 static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
-       u8 val = 0xff - s5h1420_readreg(state, 0x15);
+       u8 val = s5h1420_readreg(state, 0x15);
 
-       return (int) ((val << 8) | val);
+       *strength =  (u16) ((val << 8) | val);
+
+       return 0;
 }
 
 static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
@@ -386,7 +405,10 @@ static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 
        s5h1420_writereg(state, 0x46, 0x1f);
        mdelay(25);
-       return (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+       *ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+       return 0;
 }
 
 static void s5h1420_reset(struct s5h1420_state* state)
@@ -396,11 +418,12 @@ static void s5h1420_reset(struct s5h1420_state* state)
        udelay(10);
 }
 
-static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+static void s5h1420_setsymbolrate(struct s5h1420_state* state,
+                                 struct dvb_frontend_parameters *p)
 {
        u64 val;
 
-       val = (p->u.qpsk.symbol_rate / 1000) * (1<<24);
+       val = ((u64) p->u.qpsk.symbol_rate / 1000ULL) * (1ULL<<24);
        if (p->u.qpsk.symbol_rate <= 21000000) {
                val *= 2;
        }
@@ -415,7 +438,7 @@ static void s5h1420_setsymbolrate(struct s5h1420_state* state, struct dvb_fronte
 
 static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
 {
-       u64 val;
+       u64 val = 0;
        int sampling = 2;
 
        if (s5h1420_readreg(state, 0x05) & 0x2)
@@ -427,10 +450,10 @@ static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
        val |= s5h1420_readreg(state, 0x13);
        s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
 
-       val *= (state->fclk / 1000);
+       val *= (state->fclk / 1000ULL);
        do_div(val, ((1<<24) * sampling));
 
-       return (u32) (val * 1000);
+       return (u32) (val * 1000ULL);
 }
 
 static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
@@ -463,46 +486,55 @@ static int s5h1420_getfreqoffset(struct s5h1420_state* state)
 
        /* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
         * divide fclk by 1000000 to get the correct value. */
-       val = - ((val * (state->fclk/1000000)) / (1<<24));
+       val = (((-val) * (state->fclk/1000000)) / (1<<24));
 
        return val;
 }
 
-static void s5h1420_setfec(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
+static void s5h1420_setfec_inversion(struct s5h1420_state* state,
+                                    struct dvb_frontend_parameters *p)
 {
+       u8 inversion = 0;
+
+       if (p->inversion == INVERSION_OFF) {
+               inversion = state->config->invert ? 0x08 : 0;
+       } else if (p->inversion == INVERSION_ON) {
+               inversion = state->config->invert ? 0 : 0x08;
+       }
+
        if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
-               s5h1420_writereg(state, 0x31, 0x00);
                s5h1420_writereg(state, 0x30, 0x3f);
+               s5h1420_writereg(state, 0x31, 0x00 | inversion);
        } else {
                switch(p->u.qpsk.fec_inner) {
                case FEC_1_2:
-                       s5h1420_writereg(state, 0x31, 0x10);
                        s5h1420_writereg(state, 0x30, 0x01);
+                       s5h1420_writereg(state, 0x31, 0x10 | inversion);
                        break;
 
                case FEC_2_3:
-                       s5h1420_writereg(state, 0x31, 0x11);
                        s5h1420_writereg(state, 0x30, 0x02);
+                       s5h1420_writereg(state, 0x31, 0x11 | inversion);
                        break;
 
                case FEC_3_4:
-                       s5h1420_writereg(state, 0x31, 0x12);
                        s5h1420_writereg(state, 0x30, 0x04);
-                       break;
+                        s5h1420_writereg(state, 0x31, 0x12 | inversion);
+                        break;
 
                case FEC_5_6:
-                       s5h1420_writereg(state, 0x31, 0x13);
                        s5h1420_writereg(state, 0x30, 0x08);
+                       s5h1420_writereg(state, 0x31, 0x13 | inversion);
                        break;
 
                case FEC_6_7:
-                       s5h1420_writereg(state, 0x31, 0x14);
                        s5h1420_writereg(state, 0x30, 0x10);
+                       s5h1420_writereg(state, 0x31, 0x14 | inversion);
                        break;
 
                case FEC_7_8:
-                       s5h1420_writereg(state, 0x31, 0x15);
                        s5h1420_writereg(state, 0x30, 0x20);
+                       s5h1420_writereg(state, 0x31, 0x15 | inversion);
                        break;
 
                default:
@@ -536,22 +568,6 @@ static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
        return FEC_NONE;
 }
 
-static void s5h1420_setinversion(struct s5h1420_state* state, struct dvb_frontend_parameters *p)
-{
-       if ((p->u.qpsk.fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
-               s5h1420_writereg(state, 0x31, 0x00);
-               s5h1420_writereg(state, 0x30, 0x3f);
-       } else {
-               u8 tmp = s5h1420_readreg(state, 0x31) & 0xf7;
-                       tmp |= 0x10;
-
-               if (p->inversion == INVERSION_ON)
-                       tmp |= 0x80;
-
-               s5h1420_writereg(state, 0x31, tmp);
-       }
-}
-
 static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
 {
        if (s5h1420_readreg(state, 0x32) & 0x08)
@@ -560,35 +576,35 @@ static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
        return INVERSION_OFF;
 }
 
-static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int s5h1420_set_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *p)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
-       u32 frequency_delta;
+       int frequency_delta;
        struct dvb_frontend_tune_settings fesettings;
+       u32 tmp;
 
        /* check if we should do a fast-tune */
        memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
        s5h1420_get_tune_settings(fe, &fesettings);
        frequency_delta = p->frequency - state->tunedfreq;
-       if ((frequency_delta > -fesettings.max_drift) && (frequency_delta < fesettings.max_drift) &&
+       if ((frequency_delta > -fesettings.max_drift) &&
+           (frequency_delta < fesettings.max_drift) &&
            (frequency_delta != 0) &&
            (state->fec_inner == p->u.qpsk.fec_inner) &&
            (state->symbol_rate == p->u.qpsk.symbol_rate)) {
 
-               s5h1420_setfreqoffset(state, frequency_delta);
+               if (state->config->pll_set) {
+                       s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+                       state->config->pll_set(fe, p, &tmp);
+                       s5h1420_setfreqoffset(state, p->frequency - tmp);
+               }
                return 0;
        }
 
        /* first of all, software reset */
        s5h1420_reset(state);
 
-       /* set tuner PLL */
-       if (state->config->pll_set) {
-               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-               state->config->pll_set(fe, p, &state->tunedfreq);
-               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
-       }
-
        /* set s5h1420 fclk PLL according to desired symbol rate */
        if (p->u.qpsk.symbol_rate > 28000000) {
                state->fclk = 88000000;
@@ -609,8 +625,9 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 
        /* set misc registers */
        s5h1420_writereg(state, 0x02, 0x00);
+       s5h1420_writereg(state, 0x06, 0x00);
        s5h1420_writereg(state, 0x07, 0xb0);
-       s5h1420_writereg(state, 0x0a, 0x67);
+       s5h1420_writereg(state, 0x0a, 0xe7);
        s5h1420_writereg(state, 0x0b, 0x78);
        s5h1420_writereg(state, 0x0c, 0x48);
        s5h1420_writereg(state, 0x0d, 0x6b);
@@ -626,21 +643,26 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        /* start QPSK */
        s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
 
-       /* set the frequency offset to adjust for PLL inaccuracy */
-       s5h1420_setfreqoffset(state, p->frequency - state->tunedfreq);
+       /* set tuner PLL */
+       if (state->config->pll_set) {
+               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+               state->config->pll_set(fe, p, &tmp);
+               s5h1420_setfreqoffset(state, 0);
+       }
 
        /* set the reset of the parameters */
        s5h1420_setsymbolrate(state, p);
-       s5h1420_setinversion(state, p);
-       s5h1420_setfec(state, p);
+       s5h1420_setfec_inversion(state, p);
 
        state->fec_inner = p->u.qpsk.fec_inner;
        state->symbol_rate = p->u.qpsk.symbol_rate;
        state->postlocked = 0;
+       state->tunedfreq = p->frequency;
        return 0;
 }
 
-static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+static int s5h1420_get_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *p)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
 
@@ -652,7 +674,8 @@ static int s5h1420_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        return 0;
 }
 
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+                                    struct dvb_frontend_tune_settings* fesettings)
 {
        if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
                fesettings->min_delay_ms = 50;
@@ -717,7 +740,8 @@ static void s5h1420_release(struct dvb_frontend* fe)
 
 static struct dvb_frontend_ops s5h1420_ops;
 
-struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c)
+struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
+                                   struct i2c_adapter* i2c)
 {
        struct s5h1420_state* state = NULL;
        u8 identity;
index b687fc77ceb32729521f42452fe5b8b93cd632fe..872028ddf2a2df0e76288be17dc4a222dd457c1f 100644 (file)
@@ -30,6 +30,9 @@ struct s5h1420_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
+       /* does the inversion require inversion? */
+       u8 invert:1;
+
        /* PLL maintenance */
        int (*pll_init)(struct dvb_frontend* fe);
        int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
index 928aca052afe355c3dc6106d8c2e3dfc2a133d0f..8d09afd7545d8a054ef8efe0c1675173206f2dc6 100644 (file)
@@ -35,7 +35,6 @@ struct stv0297_state {
        struct dvb_frontend frontend;
 
        unsigned long base_freq;
-       u8 pwm;
 };
 
 #if 1
@@ -46,94 +45,6 @@ struct stv0297_state {
 
 #define STV0297_CLOCK_KHZ   28900
 
-static u8 init_tab[] = {
-       0x00, 0x09,
-       0x01, 0x69,
-       0x03, 0x00,
-       0x04, 0x00,
-       0x07, 0x00,
-       0x08, 0x00,
-       0x20, 0x00,
-       0x21, 0x40,
-       0x22, 0x00,
-       0x23, 0x00,
-       0x24, 0x40,
-       0x25, 0x88,
-       0x30, 0xff,
-       0x31, 0x00,
-       0x32, 0xff,
-       0x33, 0x00,
-       0x34, 0x50,
-       0x35, 0x7f,
-       0x36, 0x00,
-       0x37, 0x20,
-       0x38, 0x00,
-       0x40, 0x1c,
-       0x41, 0xff,
-       0x42, 0x29,
-       0x43, 0x00,
-       0x44, 0xff,
-       0x45, 0x00,
-       0x46, 0x00,
-       0x49, 0x04,
-       0x4a, 0xff,
-       0x4b, 0x7f,
-       0x52, 0x30,
-       0x55, 0xae,
-       0x56, 0x47,
-       0x57, 0xe1,
-       0x58, 0x3a,
-       0x5a, 0x1e,
-       0x5b, 0x34,
-       0x60, 0x00,
-       0x63, 0x00,
-       0x64, 0x00,
-       0x65, 0x00,
-       0x66, 0x00,
-       0x67, 0x00,
-       0x68, 0x00,
-       0x69, 0x00,
-       0x6a, 0x02,
-       0x6b, 0x00,
-       0x70, 0xff,
-       0x71, 0x00,
-       0x72, 0x00,
-       0x73, 0x00,
-       0x74, 0x0c,
-       0x80, 0x00,
-       0x81, 0x00,
-       0x82, 0x00,
-       0x83, 0x00,
-       0x84, 0x04,
-       0x85, 0x80,
-       0x86, 0x24,
-       0x87, 0x78,
-       0x88, 0x00,
-       0x89, 0x00,
-       0x90, 0x01,
-       0x91, 0x01,
-       0xa0, 0x00,
-       0xa1, 0x00,
-       0xa2, 0x00,
-       0xb0, 0x91,
-       0xb1, 0x0b,
-       0xc0, 0x53,
-       0xc1, 0x70,
-       0xc2, 0x12,
-       0xd0, 0x00,
-       0xd1, 0x00,
-       0xd2, 0x00,
-       0xd3, 0x00,
-       0xd4, 0x00,
-       0xd5, 0x00,
-       0xde, 0x00,
-       0xdf, 0x00,
-       0x61, 0x49,
-       0x62, 0x0b,
-       0x53, 0x08,
-       0x59, 0x08,
-};
-
 
 static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
 {
@@ -378,34 +289,9 @@ static int stv0297_init(struct dvb_frontend *fe)
        struct stv0297_state *state = fe->demodulator_priv;
        int i;
 
-       /* soft reset */
-       stv0297_writereg_mask(state, 0x80, 1, 1);
-       stv0297_writereg_mask(state, 0x80, 1, 0);
-
-       /* reset deinterleaver */
-       stv0297_writereg_mask(state, 0x81, 1, 1);
-       stv0297_writereg_mask(state, 0x81, 1, 0);
-
        /* load init table */
-       for (i = 0; i < sizeof(init_tab); i += 2) {
-               stv0297_writereg(state, init_tab[i], init_tab[i + 1]);
-       }
-
-       /* set a dummy symbol rate */
-       stv0297_set_symbolrate(state, 6900);
-
-       /* invert AGC1 polarity */
-       stv0297_writereg_mask(state, 0x88, 0x10, 0x10);
-
-       /* setup bit error counting */
-       stv0297_writereg_mask(state, 0xA0, 0x80, 0x00);
-       stv0297_writereg_mask(state, 0xA0, 0x10, 0x00);
-       stv0297_writereg_mask(state, 0xA0, 0x08, 0x00);
-       stv0297_writereg_mask(state, 0xA0, 0x07, 0x04);
-
-       /* min + max PWM */
-       stv0297_writereg(state, 0x4a, 0x00);
-       stv0297_writereg(state, 0x4b, state->pwm);
+       for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
+               stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
        msleep(200);
 
        if (state->config->pll_init)
@@ -606,7 +492,13 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        stv0297_set_inversion(state, inversion);
 
        /* kick off lock */
-       stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+       /* Disable corner detection for higher QAMs */
+       if (p->u.qam.modulation == QAM_128 ||
+               p->u.qam.modulation == QAM_256)
+               stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
+       else
+               stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+
        stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
        stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
        stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
@@ -732,7 +624,7 @@ static void stv0297_release(struct dvb_frontend *fe)
 static struct dvb_frontend_ops stv0297_ops;
 
 struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
-                                   struct i2c_adapter *i2c, int pwm)
+                                   struct i2c_adapter *i2c)
 {
        struct stv0297_state *state = NULL;
 
@@ -746,7 +638,6 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
        state->i2c = i2c;
        memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
        state->base_freq = 0;
-       state->pwm = pwm;
 
        /* check if the demod is there */
        if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
index 3be535989302afa168f4131eb86c2b55b5deffca..9e53f019db717e284cf50fd1b4f7390f2f173fe6 100644 (file)
@@ -29,6 +29,12 @@ struct stv0297_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
+       /* inittab - array of pairs of values.
+       * First of each pair is the register, second is the value.
+       * List should be terminated with an 0xff, 0xff pair.
+       */
+       u8* inittab;
+
        /* does the "inversion" need inverted? */
        u8 invert:1;
 
@@ -38,7 +44,7 @@ struct stv0297_config
 };
 
 extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
-                                          struct i2c_adapter* i2c, int pwm);
+                                          struct i2c_adapter* i2c);
 extern int stv0297_enable_plli2c(struct dvb_frontend* fe);
 
 #endif // STV0297_H
index cfa3928bb487bab6d61cb0991833dadf7326819a..2d62931f20b547b4588190148d879b71cda3d708 100644 (file)
@@ -63,12 +63,8 @@ struct stv0299_state {
        u32 tuner_frequency;
        u32 symbol_rate;
        fe_code_rate_t fec_inner;
-       int errmode;
 };
 
-#define STATUS_BER 0
-#define STATUS_UCBLOCKS 1
-
 static int debug;
 static int debug_legacy_dish_switch;
 #define dprintk(args...) \
@@ -481,7 +477,7 @@ static int stv0299_init (struct dvb_frontend* fe)
 
        if (state->config->pll_init) {
                stv0299_writeregI(state, 0x05, 0xb5);   /*  enable i2c repeater on stv0299  */
-               state->config->pll_init(fe);
+               state->config->pll_init(fe, state->i2c);
                stv0299_writeregI(state, 0x05, 0x35);   /*  disable i2c repeater on stv0299  */
        }
 
@@ -520,7 +516,8 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
 {
         struct stv0299_state* state = fe->demodulator_priv;
 
-       if (state->errmode != STATUS_BER) return 0;
+       stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x10);
+       msleep(100);
        *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
 
        return 0;
@@ -559,8 +556,9 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
 {
         struct stv0299_state* state = fe->demodulator_priv;
 
-       if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
-       else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
+       stv0299_writeregI(state, 0x34, (stv0299_readreg(state, 0x34) & 0xcf) | 0x30);
+       msleep(100);
+       *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
 
        return 0;
 }
@@ -603,7 +601,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
                } else {
                        /* A "normal" tune is requested */
                        stv0299_writeregI(state, 0x05, 0xb5);   /*  enable i2c repeater on stv0299  */
-                       state->config->pll_set(fe, p);
+                       state->config->pll_set(fe, state->i2c, p);
                        stv0299_writeregI(state, 0x05, 0x35);   /*  disable i2c repeater on stv0299  */
 
                        stv0299_writeregI(state, 0x32, 0x80);
@@ -615,7 +613,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
                }
        } else {
                stv0299_writeregI(state, 0x05, 0xb5);   /*  enable i2c repeater on stv0299  */
-               state->config->pll_set(fe, p);
+               state->config->pll_set(fe, state->i2c, p);
                stv0299_writeregI(state, 0x05, 0x35);   /*  disable i2c repeater on stv0299  */
 
                stv0299_set_FEC (state, p->u.qpsk.fec_inner);
@@ -709,7 +707,6 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
        state->tuner_frequency = 0;
        state->symbol_rate = 0;
        state->fec_inner = 0;
-       state->errmode = STATUS_BER;
 
        /* check if the demod is there */
        stv0299_writeregI(state, 0x02, 0x34); /* standby off */
index 79457a80a11fb77c083baa22a4d2b020f44dec52..d0c4484861e19dccd740ff361e0f0967807bc206 100644 (file)
@@ -92,8 +92,8 @@ struct stv0299_config
        int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
 
        /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+       int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c);
+       int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params);
 };
 
 extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
index ab0c032472cc01bdb6f02eefdb05966df1ba014d..74cea9f8d72106d2561aa9c4695f99853cdf9bb3 100644 (file)
@@ -1046,8 +1046,7 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
        tmp = tda1004x_read_byte(state, TDA1004X_SNR);
        if (tmp < 0)
                return -EIO;
-       if (tmp)
-               tmp = 255 - tmp;
+       tmp = 255 - tmp;
 
        *snr = ((tmp << 8) | tmp);
        dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
index 70fb44b391a75e5877b0622acc30f2ee6e5f1fc4..c6d276618e86fab9bdbbc9da7d9d5a71386772ae 100644 (file)
@@ -194,19 +194,18 @@ static int ves1820_init(struct dvb_frontend* fe)
 {
        struct ves1820_state* state = fe->demodulator_priv;
        int i;
-       int val;
 
        ves1820_writereg(state, 0, 0);
 
-       for (i = 0; i < 53; i++) {
-               val = ves1820_inittab[i];
-               if ((i == 2) && (state->config->selagc)) val |= 0x08;
-               ves1820_writereg(state, i, val);
-       }
+       for (i = 0; i < sizeof(ves1820_inittab); i++)
+               ves1820_writereg(state, i, ves1820_inittab[i]);
+       if (state->config->selagc)
+               ves1820_writereg(state, 2, ves1820_inittab[2] | 0x08);
 
        ves1820_writereg(state, 0x34, state->pwm);
 
-       if (state->config->pll_init) state->config->pll_init(fe);
+       if (state->config->pll_init)
+               state->config->pll_init(fe);
 
        return 0;
 }
@@ -234,7 +233,7 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
        ves1820_writereg(state, 0x09, reg0x09[real_qam]);
 
        ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
-
+       ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0));
        return 0;
 }
 
index e4c6e87f6c5d6228ea8f1594bc94d76391f3dfc7..22b203f8ff27a42b0693ef8061e8dda1c0c8c007 100644 (file)
@@ -168,7 +168,9 @@ static void init_av7110_av(struct av7110 *av7110)
                if (ret < 0)
                        printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
                if (rgb_on &&
-                   (av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
+                   ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
+                    (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
+                    (av7110->dev->pci->subsystem_device == 0x0000)) {
                        saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
                        //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
                }
@@ -177,9 +179,6 @@ static void init_av7110_av(struct av7110 *av7110)
        ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
        if (ret < 0)
                printk("dvb-ttpci:cannot set volume :%d\n",ret);
-       ret = av7110_setup_irc_config(av7110, 0);
-       if (ret < 0)
-               printk("dvb-ttpci:cannot setup irc config :%d\n",ret);
 }
 
 static void recover_arm(struct av7110 *av7110)
@@ -265,60 +264,6 @@ static int arm_thread(void *data)
 }
 
 
-/**
- *  Hack! we save the last av7110 ptr. This should be ok, since
- *  you rarely will use more then one IR control.
- *
- *  If we want to support multiple controls we would have to do much more...
- */
-int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
-{
-       int ret = 0;
-       static struct av7110 *last;
-
-       dprintk(4, "%p\n", av7110);
-
-       if (!av7110)
-               av7110 = last;
-       else
-               last = av7110;
-
-       if (av7110) {
-               ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
-               av7110->ir_config = ir_config;
-       }
-       return ret;
-}
-
-static void (*irc_handler)(u32);
-
-void av7110_register_irc_handler(void (*func)(u32))
-{
-       dprintk(4, "registering %p\n", func);
-       irc_handler = func;
-}
-
-void av7110_unregister_irc_handler(void (*func)(u32))
-{
-       dprintk(4, "unregistering %p\n", func);
-       irc_handler = NULL;
-}
-
-static void run_handlers(unsigned long ircom)
-{
-       if (irc_handler != NULL)
-               (*irc_handler)((u32) ircom);
-}
-
-static DECLARE_TASKLET(irtask, run_handlers, 0);
-
-static void IR_handle(struct av7110 *av7110, u32 ircom)
-{
-       dprintk(4, "ircommand = %08x\n", ircom);
-       irtask.data = (unsigned long) ircom;
-       tasklet_schedule(&irtask);
-}
-
 /****************************************************************************
  * IRQ handling
  ****************************************************************************/
@@ -711,8 +656,9 @@ static void gpioirq(unsigned long data)
                return;
 
        case DATA_IRCOMMAND:
-               IR_handle(av7110,
-                         swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
+               if (av7110->ir_handler)
+                       av7110->ir_handler(av7110,
+                               swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
                iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
                break;
 
@@ -1668,9 +1614,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
 {
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
        int ret;
        u8 data[4];
        u32 div;
@@ -1687,7 +1632,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
 
        if (params->frequency > 1530000) data[3] = 0xc0;
 
-       ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+       ret = i2c_transfer(i2c, &msg, 1);
        if (ret != 1)
                return -EIO;
        return 0;
@@ -1751,9 +1696,8 @@ static u8 alps_bsbe1_inittab[] = {
        0xff, 0xff
 };
 
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
 {
-       struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
        int ret;
        u8 data[4];
        u32 div;
@@ -1768,7 +1712,7 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
        data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
 
-       ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+       ret = i2c_transfer(i2c, &msg, 1);
        return (ret != 1) ? -EIO : 0;
 }
 
@@ -1936,6 +1880,98 @@ static struct sp8870_config alps_tdlb7_config = {
 };
 
 
+static u8 nexusca_stv0297_inittab[] = {
+       0x80, 0x01,
+       0x80, 0x00,
+       0x81, 0x01,
+       0x81, 0x00,
+       0x00, 0x09,
+       0x01, 0x69,
+       0x03, 0x00,
+       0x04, 0x00,
+       0x07, 0x00,
+       0x08, 0x00,
+       0x20, 0x00,
+       0x21, 0x40,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x24, 0x40,
+       0x25, 0x88,
+       0x30, 0xff,
+       0x31, 0x00,
+       0x32, 0xff,
+       0x33, 0x00,
+       0x34, 0x50,
+       0x35, 0x7f,
+       0x36, 0x00,
+       0x37, 0x20,
+       0x38, 0x00,
+       0x40, 0x1c,
+       0x41, 0xff,
+       0x42, 0x29,
+       0x43, 0x00,
+       0x44, 0xff,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x49, 0x04,
+       0x4a, 0x00,
+       0x4b, 0x7b,
+       0x52, 0x30,
+       0x55, 0xae,
+       0x56, 0x47,
+       0x57, 0xe1,
+       0x58, 0x3a,
+       0x5a, 0x1e,
+       0x5b, 0x34,
+       0x60, 0x00,
+       0x63, 0x00,
+       0x64, 0x00,
+       0x65, 0x00,
+       0x66, 0x00,
+       0x67, 0x00,
+       0x68, 0x00,
+       0x69, 0x00,
+       0x6a, 0x02,
+       0x6b, 0x00,
+       0x70, 0xff,
+       0x71, 0x00,
+       0x72, 0x00,
+       0x73, 0x00,
+       0x74, 0x0c,
+       0x80, 0x00,
+       0x81, 0x00,
+       0x82, 0x00,
+       0x83, 0x00,
+       0x84, 0x04,
+       0x85, 0x80,
+       0x86, 0x24,
+       0x87, 0x78,
+       0x88, 0x10,
+       0x89, 0x00,
+       0x90, 0x01,
+       0x91, 0x01,
+       0xa0, 0x04,
+       0xa1, 0x00,
+       0xa2, 0x00,
+       0xb0, 0x91,
+       0xb1, 0x0b,
+       0xc0, 0x53,
+       0xc1, 0x70,
+       0xc2, 0x12,
+       0xd0, 0x00,
+       0xd1, 0x00,
+       0xd2, 0x00,
+       0xd3, 0x00,
+       0xd4, 0x00,
+       0xd5, 0x00,
+       0xde, 0x00,
+       0xdf, 0x00,
+       0x61, 0x49,
+       0x62, 0x0b,
+       0x53, 0x08,
+       0x59, 0x08,
+       0xff, 0xff,
+};
 
 static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
@@ -1984,6 +2020,7 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
 static struct stv0297_config nexusca_stv0297_config = {
 
        .demod_address = 0x1C,
+       .inittab = nexusca_stv0297_inittab,
        .invert = 1,
        .pll_set = nexusca_stv0297_pll_set,
 };
@@ -2261,7 +2298,7 @@ static int frontend_init(struct av7110 *av7110)
 
                case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
 
-                       av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap, 0x7b);
+                       av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
                        if (av7110->fe) {
                                /* set TDA9819 into DVB mode */
                                saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
@@ -2692,7 +2729,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
                goto err_av7110_exit_v4l_12;
 
 #if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
-       av7110_ir_init();
+       av7110_ir_init(av7110);
 #endif
        printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
        av7110_num++;
@@ -2734,6 +2771,9 @@ static int av7110_detach(struct saa7146_dev* saa)
        struct av7110 *av7110 = saa->ext_priv;
        dprintk(4, "%p\n", av7110);
 
+#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
+       av7110_ir_exit(av7110);
+#endif
        if (budgetpatch) {
                /* Disable RPS1 */
                saa7146_write(saa, MC1, MASK_29);
@@ -2830,7 +2870,7 @@ static struct saa7146_pci_extension_data x_var = { \
        .ext_priv = x_name, \
        .ext = &av7110_extension }
 
-MAKE_AV7110_INFO(tts_1_X,    "Technotrend/Hauppauge WinTV DVB-S rev1.X");
+MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
 MAKE_AV7110_INFO(ttt_1_X,    "Technotrend/Hauppauge WinTV DVB-T rev1.X");
 MAKE_AV7110_INFO(ttc_1_X,    "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
 MAKE_AV7110_INFO(ttc_2_X,    "Technotrend/Hauppauge WinTV DVB-C rev2.X");
@@ -2842,16 +2882,16 @@ MAKE_AV7110_INFO(fsc,        "Fujitsu Siemens DVB-C");
 MAKE_AV7110_INFO(fss,        "Fujitsu Siemens DVB-S rev1.6");
 
 static struct pci_device_id pci_tbl[] = {
-       MAKE_EXTENSION_PCI(fsc,       0x110a, 0x0000),
-       MAKE_EXTENSION_PCI(tts_1_X,   0x13c2, 0x0000),
-       MAKE_EXTENSION_PCI(ttt_1_X,   0x13c2, 0x0001),
-       MAKE_EXTENSION_PCI(ttc_2_X,   0x13c2, 0x0002),
-       MAKE_EXTENSION_PCI(tts_2_X,   0x13c2, 0x0003),
-       MAKE_EXTENSION_PCI(fss,       0x13c2, 0x0006),
-       MAKE_EXTENSION_PCI(ttt,       0x13c2, 0x0008),
-       MAKE_EXTENSION_PCI(ttc_1_X,   0x13c2, 0x000a),
-       MAKE_EXTENSION_PCI(tts_2_3,   0x13c2, 0x000e),
-       MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
+       MAKE_EXTENSION_PCI(fsc,         0x110a, 0x0000),
+       MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
+       MAKE_EXTENSION_PCI(ttt_1_X,     0x13c2, 0x0001),
+       MAKE_EXTENSION_PCI(ttc_2_X,     0x13c2, 0x0002),
+       MAKE_EXTENSION_PCI(tts_2_X,     0x13c2, 0x0003),
+       MAKE_EXTENSION_PCI(fss,         0x13c2, 0x0006),
+       MAKE_EXTENSION_PCI(ttt,         0x13c2, 0x0008),
+       MAKE_EXTENSION_PCI(ttc_1_X,     0x13c2, 0x000a),
+       MAKE_EXTENSION_PCI(tts_2_3,     0x13c2, 0x000e),
+       MAKE_EXTENSION_PCI(tts_1_3se,   0x13c2, 0x1002),
 
 /*     MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
 /*     MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
@@ -2889,9 +2929,6 @@ static int __init av7110_init(void)
 
 static void __exit av7110_exit(void)
 {
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
-       av7110_ir_exit();
-#endif
        saa7146_unregister_extension(&av7110_extension);
 }
 
index 508b7739c6096db2c6d647b86a627a5f23117e4d..cce00ef293e94fa41daa0419f54cca8b85778d61 100644 (file)
@@ -228,7 +228,10 @@ struct av7110 {
        struct dvb_video_events  video_events;
        video_size_t             video_size;
 
-       u32                 ir_config;
+       u32                     ir_config;
+       u32                     ir_command;
+       void                    (*ir_handler)(struct av7110 *av7110, u32 ircom);
+       struct tasklet_struct   ir_tasklet;
 
        /* firmware stuff */
        unsigned char *bin_fw;
@@ -257,12 +260,10 @@ struct av7110 {
 extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
                       u16 subpid, u16 pcrpid);
 
-extern void av7110_register_irc_handler(void (*func)(u32));
-extern void av7110_unregister_irc_handler(void (*func)(u32));
 extern int av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config);
 
-extern int av7110_ir_init (void);
-extern void av7110_ir_exit (void);
+extern int av7110_ir_init(struct av7110 *av7110);
+extern void av7110_ir_exit(struct av7110 *av7110);
 
 /* msp3400 i2c subaddresses */
 #define MSP_WR_DEM 0x10
index 1220826696c5f2ba2a50a69e0b81a183c847f6a3..7442f56a72ecc77320f70d13eb68c5e8b9049f75 100644 (file)
@@ -41,6 +41,8 @@
 #include "av7110.h"
 #include "av7110_hw.h"
 
+#define _NOHANDSHAKE
+
 /****************************************************************************
  * DEBI functions
  ****************************************************************************/
@@ -364,7 +366,8 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
                msleep(1);
        }
 
-       wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
+       if (FW_VERSION(av7110->arm_app) <= 0x261f)
+               wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
 
 #ifndef _NOHANDSHAKE
        start = jiffies;
@@ -437,7 +440,8 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
 
        wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
 
-       wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
+       if (FW_VERSION(av7110->arm_app) <= 0x261f)
+               wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
 
 #ifdef COM_DEBUG
        start = jiffies;
index 665cdb8a3f718db433aa7c3c12c1b549429d3e53..357a3728ec68fe28a8a1650a117240b19d95f53f 100644 (file)
@@ -7,16 +7,16 @@
 #include <asm/bitops.h>
 
 #include "av7110.h"
+#include "av7110_hw.h"
 
-#define UP_TIMEOUT (HZ/4)
+#define UP_TIMEOUT (HZ*7/25)
 
 /* enable ir debugging by or'ing debug with 16 */
 
-static int ir_initialized;
+static int av_cnt;
+static struct av7110 *av_list[4];
 static struct input_dev input_dev;
 
-static u32 ir_config;
-
 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_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
@@ -53,8 +53,11 @@ static void av7110_emit_keyup(unsigned long data)
 static struct timer_list keyup_timer = { .function = av7110_emit_keyup };
 
 
-static void av7110_emit_key(u32 ircom)
+static void av7110_emit_key(unsigned long parm)
 {
+       struct av7110 *av7110 = (struct av7110 *) parm;
+       u32 ir_config = av7110->ir_config;
+       u32 ircom = av7110->ir_command;
        u8 data;
        u8 addr;
        static u16 old_toggle = 0;
@@ -62,19 +65,33 @@ static void av7110_emit_key(u32 ircom)
        u16 keycode;
 
        /* extract device address and data */
-       if (ir_config & 0x0001) {
-               /* TODO RCMM: ? bits device address, 8 bits data */
+       switch (ir_config & 0x0003) {
+       case 0: /* RC5: 5 bits device address, 6 bits data */
+               data = ircom & 0x3f;
+               addr = (ircom >> 6) & 0x1f;
+               break;
+
+       case 1: /* RCMM: 8(?) bits device address, 8(?) bits data */
                data = ircom & 0xff;
                addr = (ircom >> 8) & 0xff;
-       } else {
-               /* RC5: 5 bits device address, 6 bits data */
+               break;
+
+       case 2: /* extended RC5: 5 bits device address, 7 bits data */
                data = ircom & 0x3f;
                addr = (ircom >> 6) & 0x1f;
+               /* invert 7th data bit for backward compatibility with RC5 keymaps */
+               if (!(ircom & 0x1000))
+                       data |= 0x40;
+               break;
+
+       default:
+               printk("invalid ir_config %x\n", ir_config);
+               return;
        }
 
        keycode = key_map[data];
 
-       dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n",
+       dprintk(16, "code %08x -> addr %i data 0x%02x -> keycode %i\n",
                ircom, addr, data, keycode);
 
        /* check device address (if selected) */
@@ -87,10 +104,10 @@ static void av7110_emit_key(u32 ircom)
                return;
        }
 
-       if (ir_config & 0x0001)
+       if ((ir_config & 0x0003) == 1)
                new_toggle = 0; /* RCMM */
        else
-               new_toggle = (ircom & 0x800); /* RC5 */
+               new_toggle = (ircom & 0x800); /* RC5, extended RC5 */
 
        if (timer_pending(&keyup_timer)) {
                del_timer(&keyup_timer);
@@ -137,6 +154,8 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
 {
        char *page;
        int size = 4 + 256 * sizeof(u16);
+       u32 ir_config;
+       int i;
 
        if (count < size)
                return -EINVAL;
@@ -153,60 +172,95 @@ static int av7110_ir_write_proc(struct file *file, const char __user *buffer,
        memcpy(&ir_config, page, 4);
        memcpy(&key_map, page + 4, 256 * sizeof(u16));
        vfree(page);
-       av7110_setup_irc_config(NULL, ir_config);
+       if (FW_VERSION(av_list[0]->arm_app) >= 0x2620 && !(ir_config & 0x0001))
+               ir_config |= 0x0002; /* enable extended RC5 */
+       for (i = 0; i < av_cnt; i++)
+               av7110_setup_irc_config(av_list[i], ir_config);
        input_register_keys();
        return count;
 }
 
 
-int __init av7110_ir_init(void)
+int av7110_setup_irc_config(struct av7110 *av7110, u32 ir_config)
 {
-       static struct proc_dir_entry *e;
+       int ret = 0;
 
-       if (ir_initialized)
-               return 0;
+       dprintk(4, "%p\n", av7110);
+       if (av7110) {
+               ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config);
+               av7110->ir_config = ir_config;
+       }
+       return ret;
+}
 
-       init_timer(&keyup_timer);
-       keyup_timer.data = 0;
 
-       input_dev.name = "DVB on-card IR receiver";
+static void ir_handler(struct av7110 *av7110, u32 ircom)
+{
+       dprintk(4, "ircommand = %08x\n", ircom);
+       av7110->ir_command = ircom;
+       tasklet_schedule(&av7110->ir_tasklet);
+}
 
-       /**
-        *  enable keys
-        */
-       set_bit(EV_KEY, input_dev.evbit);
-       set_bit(EV_REP, input_dev.evbit);
 
-       input_register_keys();
+int __init av7110_ir_init(struct av7110 *av7110)
+{
+       static struct proc_dir_entry *e;
 
-       input_register_device(&input_dev);
-       input_dev.timer.function = input_repeat_key;
+       if (av_cnt >= sizeof av_list/sizeof av_list[0])
+               return -ENOSPC;
 
-       av7110_setup_irc_config(NULL, 0x0001);
-       av7110_register_irc_handler(av7110_emit_key);
+       av7110_setup_irc_config(av7110, 0x0001);
+       av_list[av_cnt++] = av7110;
 
-       e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
-       if (e) {
-               e->write_proc = av7110_ir_write_proc;
-               e->size = 4 + 256 * sizeof(u16);
+       if (av_cnt == 1) {
+               init_timer(&keyup_timer);
+               keyup_timer.data = 0;
+
+               input_dev.name = "DVB on-card IR receiver";
+               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;
+
+               e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
+               if (e) {
+                       e->write_proc = av7110_ir_write_proc;
+                       e->size = 4 + 256 * sizeof(u16);
+               }
        }
 
-       ir_initialized = 1;
+       tasklet_init(&av7110->ir_tasklet, av7110_emit_key, (unsigned long) av7110);
+       av7110->ir_handler = ir_handler;
+
        return 0;
 }
 
 
-void __exit av7110_ir_exit(void)
+void __exit av7110_ir_exit(struct av7110 *av7110)
 {
-       if (ir_initialized == 0)
+       int i;
+
+       if (av_cnt == 0)
                return;
-       del_timer_sync(&keyup_timer);
-       remove_proc_entry("av7110_ir", NULL);
-       av7110_unregister_irc_handler(av7110_emit_key);
-       input_unregister_device(&input_dev);
-       ir_initialized = 0;
+
+       av7110->ir_handler = NULL;
+       tasklet_kill(&av7110->ir_tasklet);
+       for (i = 0; i < av_cnt; i++)
+               if (av_list[i] == av7110) {
+                       av_list[i] = av_list[av_cnt-1];
+                       av_list[av_cnt-1] = NULL;
+                       break;
+               }
+
+       if (av_cnt == 1) {
+               del_timer_sync(&keyup_timer);
+               remove_proc_entry("av7110_ir", NULL);
+               input_unregister_device(&input_dev);
+       }
+
+       av_cnt--;
 }
 
 //MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
 //MODULE_LICENSE("GPL");
-
index e65fc36e2ce8327884fa02f38d8bfc62bcfba487..6af74f78b3e505a931d125814a12490b315b7efb 100644 (file)
@@ -70,7 +70,7 @@ static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
        return 0;
 }
 
-static struct v4l2_input inputs[2] = {
+static struct v4l2_input inputs[4] = {
        {
                .index          = 0,
                .name           = "DVB",
@@ -87,6 +87,22 @@ static struct v4l2_input inputs[2] = {
                .tuner          = 0,
                .std            = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
                .status         = 0,
+       }, {
+               .index          = 2,
+               .name           = "Video",
+               .type           = V4L2_INPUT_TYPE_CAMERA,
+               .audioset       = 0,
+               .tuner          = 0,
+               .std            = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+               .status         = 0,
+       }, {
+               .index          = 3,
+               .name           = "Y/C",
+               .type           = V4L2_INPUT_TYPE_CAMERA,
+               .audioset       = 0,
+               .tuner          = 0,
+               .std            = V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
+               .status         = 0,
        }
 };
 
@@ -212,24 +228,44 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
        }
 
        if (0 != av7110->current_input) {
+               dprintk(1, "switching to analog TV:\n");
                adswitch = 1;
                source = SAA7146_HPS_SOURCE_PORT_B;
                sync = SAA7146_HPS_SYNC_PORT_B;
                memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
-               dprintk(1, "switching to analog TV\n");
-               msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
-               msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
-               msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
-               msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
-               msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
-               msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
 
-               if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
-                       if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
-                               dprintk(1, "setting band in demodulator failed.\n");
-               } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-                       saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
-                       saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+               switch (av7110->current_input) {
+               case 1:
+                       dprintk(1, "switching SAA7113 to Analog Tuner Input.\n");
+                       msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
+                       msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
+                       msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
+                       msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
+                       msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
+                       msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
+
+                       if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
+                               if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
+                                       dprintk(1, "setting band in demodulator failed.\n");
+                       } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
+                               saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
+                               saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+                       }
+                       if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
+                               dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+                       break;
+               case 2:
+                       dprintk(1, "switching SAA7113 to Video AV CVBS Input.\n");
+                       if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
+                               dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+                       break;
+               case 3:
+                       dprintk(1, "switching SAA7113 to Video AV Y/C Input.\n");
+                       if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
+                               dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
+                       break;
+               default:
+                       dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input.\n");
                }
        } else {
                adswitch = 0;
@@ -300,7 +336,6 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                // FIXME: standard / stereo detection is still broken
                msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
                dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
-
                msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
                dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
                stereo = (s8)(stereo_det >> 8);
@@ -310,7 +345,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                        t->audmode = V4L2_TUNER_MODE_STEREO;
                }
                else if (stereo < -0x10) {
-                       /* bilingual*/
+                       /* bilingual */
                        t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
                        t->audmode = V4L2_TUNER_MODE_LANG1;
                }
@@ -344,7 +379,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                        fm_matrix = 0x3000; // mono
                        src = 0x0010;
                        break;
-               default: /* case V4L2_TUNER_MODE_MONO: {*/
+               default: /* case V4L2_TUNER_MODE_MONO: */
                        dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
                        fm_matrix = 0x3000; // mono
                        src = 0x0030;
@@ -406,7 +441,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
 
                if (av7110->analog_tuner_flags) {
-                       if (i->index < 0 || i->index >= 2)
+                       if (i->index < 0 || i->index >= 4)
                                return -EINVAL;
                } else {
                        if (i->index != 0)
@@ -433,10 +468,9 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
                if (!av7110->analog_tuner_flags)
                        return 0;
 
-               if (input < 0 || input >= 2)
+               if (input < 0 || input >= 4)
                        return -EINVAL;
 
-               /* FIXME: switch inputs here */
                av7110->current_input = input;
                return av7110_dvb_c_switch(fh);
        }
index 9746d2bb916f3fcfe711772a729a503e709ced52..7692cd23f839cb13fb865c25196b179aa1f279c2 100644 (file)
@@ -192,7 +192,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 {
        struct budget_av *budget_av = (struct budget_av *) ca->data;
        struct saa7146_dev *saa = budget_av->budget.dev;
-       int timeout = 50; // 5 seconds (4.4.6 Ready)
+       int timeout = 500; // 5 seconds (4.4.6 Ready)
 
        if (slot != 0)
                return -EINVAL;
@@ -217,7 +217,6 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
        {
                printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
                saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-               saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
                return -ETIMEDOUT;
        }
 
@@ -276,7 +275,6 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
                {
                        printk(KERN_INFO "budget-av: cam ejected\n");
                        saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-                       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
                        budget_av->slot_status = 0;
                }
        }
@@ -453,9 +451,9 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
 }
 
 static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
+                                       struct i2c_adapter *i2c,
                                        struct dvb_frontend_parameters *params)
 {
-       struct budget_av *budget_av = (struct budget_av *) fe->dvb->priv;
        u32 div;
        u8 buf[4];
        struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -481,7 +479,7 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
        else if (params->frequency < 2150000)
                buf[3] |= 0xC0;
 
-       if (i2c_transfer(&budget_av->budget.i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(i2c, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -745,6 +743,7 @@ static void frontend_init(struct budget_av *budget_av)
                case SUBID_DVBC_KNC1_PLUS:
                case SUBID_DVBT_KNC1_PLUS:
                        // Enable / PowerON Frontend
+                       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
                        saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
                        break;
        }
index a1267054bc018f7cde8b428dfe7fdd9d3d71b50a..2980db3ef22f8c2a90021bd334a5614a0d049893 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "dvb_ca_en50221.h"
 #include "stv0299.h"
+#include "stv0297.h"
 #include "tda1004x.h"
 
 #define DEBIADDR_IR            0x1234
@@ -548,9 +549,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
 {
-       struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -567,7 +567,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct dvb_frontend_param
        if (params->frequency > 1530000)
                buf[3] = 0xc0;
 
-       if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(i2c, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -669,9 +669,9 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
 }
 
 static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
+                                    struct i2c_adapter *i2c,
                                     struct dvb_frontend_parameters *params)
 {
-       struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u32 div;
        u8 buf[4];
        struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -697,7 +697,7 @@ static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
        else if (params->frequency < 2150000)
                buf[3] |= 0xC0;
 
-       if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(i2c, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -848,6 +848,180 @@ static struct tda1004x_config philips_tdm1316l_config = {
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
+static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+       u8 tuner_buf[5];
+       struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
+                                   .flags = 0,
+                                   .buf = tuner_buf,
+                                   .len = sizeof(tuner_buf) };
+       int tuner_frequency = 0;
+       u8 band, cp, filter;
+
+       // determine charge pump
+       tuner_frequency = params->frequency + 36125000;
+       if (tuner_frequency < 87000000)
+               return -EINVAL;
+       else if (tuner_frequency < 130000000) {
+               cp = 3;
+               band = 1;
+       } else if (tuner_frequency < 160000000) {
+               cp = 5;
+               band = 1;
+       } else if (tuner_frequency < 200000000) {
+               cp = 6;
+               band = 1;
+       } else if (tuner_frequency < 290000000) {
+               cp = 3;
+               band = 2;
+       } else if (tuner_frequency < 420000000) {
+               cp = 5;
+               band = 2;
+       } else if (tuner_frequency < 480000000) {
+               cp = 6;
+               band = 2;
+       } else if (tuner_frequency < 620000000) {
+               cp = 3;
+               band = 4;
+       } else if (tuner_frequency < 830000000) {
+               cp = 5;
+               band = 4;
+       } else if (tuner_frequency < 895000000) {
+               cp = 7;
+               band = 4;
+       } else
+               return -EINVAL;
+
+       // assume PLL filter should always be 8MHz for the moment.
+       filter = 1;
+
+       // calculate divisor
+       tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
+
+       // setup tuner buffer
+       tuner_buf[0] = tuner_frequency >> 8;
+       tuner_buf[1] = tuner_frequency & 0xff;
+       tuner_buf[2] = 0xc8;
+       tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+       tuner_buf[4] = 0x80;
+
+       stv0297_enable_plli2c(fe);
+       if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+               return -EIO;
+
+       msleep(50);
+
+       stv0297_enable_plli2c(fe);
+       if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+               return -EIO;
+
+       msleep(1);
+
+       return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+       0x80, 0x01,
+       0x80, 0x00,
+       0x81, 0x01,
+       0x81, 0x00,
+       0x00, 0x09,
+       0x01, 0x69,
+       0x03, 0x00,
+       0x04, 0x00,
+       0x07, 0x00,
+       0x08, 0x00,
+       0x20, 0x00,
+       0x21, 0x40,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x24, 0x40,
+       0x25, 0x88,
+       0x30, 0xff,
+       0x31, 0x00,
+       0x32, 0xff,
+       0x33, 0x00,
+       0x34, 0x50,
+       0x35, 0x7f,
+       0x36, 0x00,
+       0x37, 0x20,
+       0x38, 0x00,
+       0x40, 0x1c,
+       0x41, 0xff,
+       0x42, 0x29,
+       0x43, 0x20,
+       0x44, 0xff,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x49, 0x04,
+       0x4a, 0x00,
+       0x4b, 0x7b,
+       0x52, 0x30,
+       0x55, 0xae,
+       0x56, 0x47,
+       0x57, 0xe1,
+       0x58, 0x3a,
+       0x5a, 0x1e,
+       0x5b, 0x34,
+       0x60, 0x00,
+       0x63, 0x00,
+       0x64, 0x00,
+       0x65, 0x00,
+       0x66, 0x00,
+       0x67, 0x00,
+       0x68, 0x00,
+       0x69, 0x00,
+       0x6a, 0x02,
+       0x6b, 0x00,
+       0x70, 0xff,
+       0x71, 0x00,
+       0x72, 0x00,
+       0x73, 0x00,
+       0x74, 0x0c,
+       0x80, 0x00,
+       0x81, 0x00,
+       0x82, 0x00,
+       0x83, 0x00,
+       0x84, 0x04,
+       0x85, 0x80,
+       0x86, 0x24,
+       0x87, 0x78,
+       0x88, 0x10,
+       0x89, 0x00,
+       0x90, 0x01,
+       0x91, 0x01,
+       0xa0, 0x04,
+       0xa1, 0x00,
+       0xa2, 0x00,
+       0xb0, 0x91,
+       0xb1, 0x0b,
+       0xc0, 0x53,
+       0xc1, 0x70,
+       0xc2, 0x12,
+       0xd0, 0x00,
+       0xd1, 0x00,
+       0xd2, 0x00,
+       0xd3, 0x00,
+       0xd4, 0x00,
+       0xd5, 0x00,
+       0xde, 0x00,
+       0xdf, 0x00,
+       0x61, 0x38,
+       0x62, 0x0a,
+       0x53, 0x13,
+       0x59, 0x08,
+       0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+       .demod_address = 0x1c,
+       .inittab = dvbc_philips_tdm1316l_inittab,
+       .invert = 0,
+       .pll_set = dvbc_philips_tdm1316l_pll_set,
+};
+
+
 
 
 static void frontend_init(struct budget_ci *budget_ci)
@@ -869,6 +1043,15 @@ static void frontend_init(struct budget_ci *budget_ci)
                }
                break;
 
+       case 0x1010:            // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
+               budget_ci->tuner_pll_address = 0x61;
+               budget_ci->budget.dvb_frontend =
+                       stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+               if (budget_ci->budget.dvb_frontend) {
+                       break;
+               }
+               break;
+
        case 0x1011:            // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
                budget_ci->tuner_pll_address = 0x63;
                budget_ci->budget.dvb_frontend =
@@ -878,7 +1061,7 @@ static void frontend_init(struct budget_ci *budget_ci)
                }
                break;
 
-       case 0x1012:            // Hauppauge/TT Nova-T CI budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
+       case 0x1012:            // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
                budget_ci->tuner_pll_address = 0x60;
                budget_ci->budget.dvb_frontend =
                        tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
@@ -966,10 +1149,12 @@ static struct saa7146_extension budget_extension;
 MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
 MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T         PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
        MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
+       MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
        MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
        MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
        {
index 8142e26b47f5d4bb5e2f460245e48254a2b7f96c..b1f21ef0e3b39ec6b3f2229608e0d04f22430af3 100644 (file)
@@ -353,9 +353,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
 {
-       struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
        u8 data[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -370,7 +369,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
 
        if (params->frequency > 1530000) data[3] = 0xc0;
 
-       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+       if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
index 9961917e8a7fd9c99501a15317c69cbcbd5e3bb4..43d6c8268642b5670a5fe40bb4c828b5e1c8ff96 100644 (file)
@@ -332,9 +332,8 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
 {
-       struct budget* budget = (struct budget*) fe->dvb->priv;
        u8 data[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
@@ -349,7 +348,7 @@ static int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
 
        if (params->frequency > 1530000) data[3] = 0xc0;
 
-       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+       if (i2c_transfer(i2c, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
@@ -481,6 +480,7 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
 
 static struct s5h1420_config s5h1420_config = {
        .demod_address = 0x53,
+       .invert = 1,
        .pll_set = s5h1420_pll_set,
 };
 
index 7daf7b1598a0d4dfb96c37daf6b406044d03bf8c..d200ab0ad9e7fbf05c5d3225aabe1add5988c71c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/errno.h>
+#include <linux/jiffies.h>
 #include <asm/semaphore.h>
 
 #include "dvb_frontend.h"
@@ -570,7 +571,8 @@ static void ttusb_handle_sec_data(struct ttusb_channel *channel,
                                  const u8 * data, int len);
 #endif
 
-static int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid;
+static int numpkt = 0, numts, numstuff, numsec, numinvalid;
+static unsigned long lastj;
 
 static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
                           int len)
@@ -779,7 +781,7 @@ static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs)
                        u8 *data;
                        int len;
                        numpkt++;
-                       if ((jiffies - lastj) >= HZ) {
+                       if (time_after_eq(jiffies, lastj + HZ)) {
 #if DEBUG > 2
                                printk
                                    ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
@@ -1299,7 +1301,7 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
        return 0;
 }
 
-static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
 {
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 buf[4];
@@ -1322,7 +1324,7 @@ static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
        if (ttusb->revision == TTUSB_REV_2_2)
                buf[3] |= 0x20;
 
-       if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
+       if (i2c_transfer(i2c, &msg, 1) != 1)
                return -EIO;
 
        return 0;
index 45c9a9a08e4d8ecea7b940d149cef87d609ad310..3d08fc83a7541a45c5a5e076925fe80ef008baca 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
-#include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/firmware.h>
 #include <linux/crc32.h>
index 16c85c081e6ebe1533462a08084d0427a93f90bb..93570355819aefd3c36cc35f25343f24370d9a36 100644 (file)
@@ -22,12 +22,21 @@ config VIDEO_BT848
          the Miro, Hauppauge and STB boards. Please read the material in
          <file:Documentation/video4linux/bttv/> for more information.
 
-         If you say Y or M here, you need to say Y or M to "I2C support" and
-         "I2C bit-banging interfaces" in the device drivers section.
-
          To compile this driver as a module, choose M here: the
          module will be called bttv.
 
+config VIDEO_SAA6588
+       tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards"
+       depends on VIDEO_DEV && I2C && VIDEO_BT848
+
+       help
+         Support for  Radio Data System (RDS) decoder. This allows seeing
+         radio station identification transmitted using this standard.
+         Currentlly, it works only with bt8x8 chips.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa6588.
+
 config VIDEO_PMS
        tristate "Mediavision Pro Movie Studio Video For Linux"
        depends on VIDEO_DEV && ISA
index 3e6f5347da21ef90f97e99a0c651d28fc1edf070..046b82de92859c52e92812ed4235f2cdd7a8ff4a 100644 (file)
@@ -5,6 +5,7 @@
 bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
                        bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o
 zoran-objs      :=     zr36120.o zr36120_i2c.o zr36120_mem.o
+rds-objs        :=     saa6588.o
 zr36067-objs   :=      zoran_procfs.o zoran_device.o \
                        zoran_driver.o zoran_card.o
 tuner-objs     :=      tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
 obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
 obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
+obj-$(CONFIG_VIDEO_SAA6588) += rds.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
 obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
 obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
index 7f2d515d28737e74f324ac7aafc5d3250c28890c..a48de3c0e3f0055c586e30fb55b20293663ba937 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: btcx-risc.c,v 1.6 2005/02/21 13:57:59 kraxel Exp $
 
     btcx-risc.c
 
index 41f60395a5203de439073d9721fded86b2536bbb..503e6c6d7b6917d5e46a7059245242ed1f66286f 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: btcx-risc.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $
  */
 struct btcx_riscmem {
        unsigned int   size;
index a97b9b958ed6d4ca3858519dec5750c6bc8198b0..190977a1e5494598b753d3a34ea5c2a60ad989b6 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-cards.c,v 1.54 2005/07/19 18:26:46 mkrufky Exp $
 
     bttv-cards.c
 
@@ -169,10 +168,10 @@ static struct CARD {
        { 0xd01810fc, BTTV_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
 
        { 0x001211bd, BTTV_PINNACLE,      "Pinnacle PCTV" },
-       // some cards ship with byteswapped IDs ...
+       /* some cards ship with byteswapped IDs ... */
        { 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
        { 0xff00bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
-       // this seems to happen as well ...
+       /* this seems to happen as well ... */
        { 0xff1211bd, BTTV_PINNACLE,      "Pinnacle PCTV" },
 
        { 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
@@ -200,12 +199,12 @@ static struct CARD {
 
        { 0x1123153b, BTTV_TERRATVRADIO,  "Terratec TV Radio+" },
        { 0x1127153b, BTTV_TERRATV,       "Terratec TV+ (V1.05)"    },
-       // clashes with FlyVideo
-       //{ 0x18521852, BTTV_TERRATV,     "Terratec TV+ (V1.10)"    },
+       /* clashes with FlyVideo
+        *{ 0x18521852, BTTV_TERRATV,     "Terratec TV+ (V1.10)"    }, */
        { 0x1134153b, BTTV_TERRATVALUE,   "Terratec TValue (LR102)" },
-       { 0x1135153b, BTTV_TERRATVALUER,  "Terratec TValue Radio" }, // LR102
-       { 0x5018153b, BTTV_TERRATVALUE,   "Terratec TValue" },       // ??
-       { 0xff3b153b, BTTV_TERRATVALUER,  "Terratec TValue Radio" }, // ??
+       { 0x1135153b, BTTV_TERRATVALUER,  "Terratec TValue Radio" }, /* LR102 */
+       { 0x5018153b, BTTV_TERRATVALUE,   "Terratec TValue" },       /* ?? */
+       { 0xff3b153b, BTTV_TERRATVALUER,  "Terratec TValue Radio" }, /* ?? */
 
        { 0x400015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
        { 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
@@ -287,10 +286,12 @@ static struct CARD {
        { 0x01071805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
        { 0x01081805, BTTV_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
 
-       // likely broken, vendor id doesn't match the other magic views ...
-       //{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
+       { 0x15409511, BTTV_ACORP_Y878F, "Acorp Y878F" },
 
-       // DVB cards (using pci function .1 for mpeg data xfer)
+       /* likely broken, vendor id doesn't match the other magic views ...
+        * { 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+
+       /* DVB cards (using pci function .1 for mpeg data xfer) */
        { 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
        { 0x07611461, BTTV_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
        { 0x001c11bd, BTTV_PINNACLESAT,   "Pinnacle PCTV Sat" },
@@ -298,7 +299,8 @@ static struct CARD {
        { 0x00011822, BTTV_TWINHAN_DST,   "Twinhan VisionPlus DVB" },
        { 0xfc00270f, BTTV_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
        { 0x07711461, BTTV_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
-       { 0xdb1018ac, BTTV_DVICO_DVBT_LITE,    "DVICO FusionHDTV DVB-T Lite" },
+       { 0xdb1018ac, BTTV_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
+       { 0xd50018ac, BTTV_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
 
        { 0, -1, NULL }
 };
@@ -316,6 +318,7 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 2,
        .muxsel         = { 2, 3, 1, 0},
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "MIRO PCTV",
        .video_inputs   = 4,
@@ -327,6 +330,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 2, 0, 0, 0, 10},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Hauppauge (bt848)",
        .video_inputs   = 4,
@@ -338,6 +342,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 1, 2, 3, 4},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "STB, Gateway P/N 6000699 (bt848)",
        .video_inputs   = 3,
@@ -350,6 +355,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .needs_tvaudio  = 1,
        .tuner_type     = TUNER_PHILIPS_NTSC,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_28,
        .has_radio      = 1,
 },{
@@ -365,6 +371,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0 },
        .needs_tvaudio  = 0,
        .tuner_type     = 4,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Diamond DTV2000",
        .video_inputs   = 4,
@@ -376,6 +383,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 1, 0, 1, 3},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "AVerMedia TVPhone",
        .video_inputs   = 3,
@@ -388,6 +396,7 @@ struct tvcard bttv_tvcards[] = {
        /*                0x04 for some cards ?? */
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = avermedia_tvphone_audio,
        .has_remote     = 1,
 },{
@@ -401,6 +410,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = {0 },
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x08 ---------------------------------- */
@@ -415,6 +425,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "IMS/IXmicro TurboTV",
        .video_inputs   = 3,
@@ -427,6 +438,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = TUNER_TEMIC_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Hauppauge (bt878)",
        .video_inputs   = 4,
@@ -439,6 +451,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "MIRO PCTV pro",
        .video_inputs   = 3,
@@ -450,6 +463,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0x20001,0x10001, 0, 0,10},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x0c ---------------------------------- */
@@ -463,6 +477,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 13, 14, 11, 7, 0, 0},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "AVerMedia TVCapture 98",
        .video_inputs   = 3,
@@ -476,6 +491,7 @@ struct tvcard bttv_tvcards[] = {
        .msp34xx_alt    = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = avermedia_tv_stereo_audio,
 },{
        .name           = "Aimslab Video Highway Xtreme (VHX)",
@@ -489,6 +505,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Zoltrix TV-Max",
        .video_inputs   = 3,
@@ -500,6 +517,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = {0 , 0, 1 , 0, 10},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x10 ---------------------------------- */
@@ -510,7 +528,7 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 2,
        .gpiomask       = 0x01fe00,
        .muxsel         = { 2, 3, 1, 1},
-       // 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru>
+       /* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
        .audiomux       = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
@@ -526,6 +544,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = winview_audio,
        .has_radio      = 1,
 },{
@@ -539,6 +558,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = {1, 0, 0, 0, 0},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
        .video_inputs   = 4,
@@ -550,6 +570,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0 },
        .no_msp34xx     = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x14 ---------------------------------- */
@@ -560,10 +581,11 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 2,
        .muxsel         = {2, 3, 1, 1},
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50",
        .video_inputs   = 4,
-       .audio_inputs   = 2,  // tuner, line in
+       .audio_inputs   = 2,  /* tuner, line in */
        .tuner          = 0,
        .svhs           = 2,
        .gpiomask       = 0x1800,
@@ -571,6 +593,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 0x800, 0x1000, 0x1000, 0x1800},
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL_I,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Askey CPH050/ Phoebe Tv Master + FM",
        .video_inputs   = 3,
@@ -583,6 +606,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
        .video_inputs   = 3,
@@ -591,11 +615,12 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = -1,
        .gpiomask       = 7,
        .muxsel         = { 2, 3, -1 },
-        .digital_mode   = DIGITAL_MODE_CAMERA,
+       .digital_mode   = DIGITAL_MODE_CAMERA,
        .audiomux       = { 0, 0, 0, 0, 0 },
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_ALPS_TSBB5_PAL_I,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x18 ---------------------------------- */
@@ -610,6 +635,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .has_remote     = 1,
 },{
        .name           = "Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar",
@@ -622,6 +648,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0x20000, 0x30000, 0x10000, 0, 0x40000},
        .needs_tvaudio  = 0,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = terratv_audio,
 },{
        .name           = "Hauppauge WinCam newer (bt878)",
@@ -634,6 +661,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 1, 2, 3, 4},
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
        .video_inputs   = 4,
@@ -645,6 +673,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 0x800, 0x1000, 0x1000, 0x1800},
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_SECAM,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x1c ---------------------------------- */
@@ -658,37 +687,38 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
        .needs_tvaudio  = 0,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = terratv_audio,
        /* GPIO wiring:
-               External 20 pin connector (for Active Radio Upgrade board)
-               gpio00: i2c-sda
-               gpio01: i2c-scl
-               gpio02: om5610-data
-               gpio03: om5610-clk
-               gpio04: om5610-wre
-               gpio05: om5610-stereo
-               gpio06: rds6588-davn
-               gpio07: Pin 7 n.c.
-               gpio08: nIOW
-               gpio09+10: nIOR, nSEL ?? (bt878)
-                gpio09: nIOR (bt848)
-                gpio10: nSEL (bt848)
-              Sound Routing:
-               gpio16: u2-A0 (1st 4052bt)
-               gpio17: u2-A1
-               gpio18: u2-nEN
-               gpio19: u4-A0 (2nd 4052)
-               gpio20: u4-A1
-                       u4-nEN - GND
-           Btspy:
-               00000 : Cdrom (internal audio input)
+       External 20 pin connector (for Active Radio Upgrade board)
+       gpio00: i2c-sda
+       gpio01: i2c-scl
+       gpio02: om5610-data
+       gpio03: om5610-clk
+       gpio04: om5610-wre
+       gpio05: om5610-stereo
+       gpio06: rds6588-davn
+       gpio07: Pin 7 n.c.
+       gpio08: nIOW
+       gpio09+10: nIOR, nSEL ?? (bt878)
+               gpio09: nIOR (bt848)
+               gpio10: nSEL (bt848)
+       Sound Routing:
+       gpio16: u2-A0 (1st 4052bt)
+       gpio17: u2-A1
+       gpio18: u2-nEN
+       gpio19: u4-A0 (2nd 4052)
+       gpio20: u4-A1
+               u4-nEN - GND
+       Btspy:
+               00000 : Cdrom (internal audio input)
                10000 : ext. Video audio input
                20000 : TV Mono
                a0000 : TV Mono/2
-              1a0000 : TV Stereo
+       1a0000 : TV Stereo
                30000 : Radio
                40000 : Mute
-       */
+*/
 
 },{
        /* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
@@ -702,6 +732,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0 },
        .needs_tvaudio  = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .muxsel_hook    = PXC200_muxsel,
 
 },{
@@ -710,11 +741,12 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 1,
        .tuner          = 0,
        .svhs           = 2,
-       .gpiomask       = 0x1800,  //0x8dfe00
+       .gpiomask       = 0x1800,  /* 0x8dfe00 */
        .muxsel         = { 2, 3, 1, 1},
        .audiomux       = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Formac iProTV, Formac ProTV I (bt848)",
        .video_inputs   = 4,
@@ -726,6 +758,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 1, 0, 0, 0, 0 },
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x20 ---------------------------------- */
@@ -739,6 +772,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0 },
        .needs_tvaudio  = 0,
        .tuner_type     = 4,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Terratec TerraTValue Version Bt878",
        .video_inputs   = 3,
@@ -751,31 +785,33 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Leadtek WinFast 2000/ WinFast 2000 XP",
        .video_inputs   = 4,
        .audio_inputs   = 1,
        .tuner          = 0,
        .svhs           = 2,
-       .muxsel         = { 2, 3, 1, 1, 0}, // TV, CVid, SVid, CVid over SVid connector
+       .muxsel         = { 2, 3, 1, 1, 0}, /* TV, CVid, SVid, CVid over SVid connector */
        /* Alexander Varakin <avarakin@hotmail.com> [stereo version] */
        .gpiomask       = 0xb33000,
        .audiomux       = { 0x122000,0x1000,0x0000,0x620000,0x800000 },
        /* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
                gpio23 -- hef4052:nEnable (0x800000)
                gpio12 -- hef4052:A1
-               gpio13 -- hef4052:A0
-           0x0000: external audio
-           0x1000: FM
-           0x2000: TV
-           0x3000: n.c.
-          Note: There exists another variant "Winfast 2000" with tv stereo !?
-         Note: eeprom only contains FF and pci subsystem id 107d:6606
-        */
+               gpio13 -- hef4052:A0
+       0x0000: external audio
+       0x1000: FM
+       0x2000: TV
+       0x3000: n.c.
+       Note: There exists another variant "Winfast 2000" with tv stereo !?
+       Note: eeprom only contains FF and pci subsystem id 107d:6606
+       */
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .has_radio      = 1,
-       .tuner_type     = 5, // default for now, gpio reads BFFF06 for Pal bg+dk
+       .tuner_type     = 5, /* default for now, gpio reads BFFF06 for Pal bg+dk */
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = winfast2000_audio,
        .has_remote     = 1,
 },{
@@ -789,6 +825,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 0x800, 0x1000, 0x1000, 0x1800},
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x24 ---------------------------------- */
@@ -802,6 +839,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .has_radio      = 1,
 },{
        .name           = "Prolink PixelView PlayTV pro",
@@ -815,6 +853,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Askey CPH06X TView99",
        .video_inputs   = 4,
@@ -827,6 +866,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = 1,
+       .tuner_addr     = ADDR_UNSET,
        .has_remote     = 1,
 },{
        .name           = "Pinnacle PCTV Studio/Rave",
@@ -840,6 +880,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x28 ---------------------------------- */
@@ -854,6 +895,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .needs_tvaudio  = 1,
        .tuner_type     = TUNER_PHILIPS_NTSC,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_28,
        .has_radio      = 1,
 },{
@@ -868,6 +910,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .has_radio      = 1,
        .audio_hook     = avermedia_tvphone_audio,
 },{
@@ -883,6 +926,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = 1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Little OnAir TV",
        .video_inputs   = 3,
@@ -894,6 +938,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},
        .no_msp34xx     = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x2c ---------------------------------- */
@@ -908,6 +953,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_NONE,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "MATRIX-Vision MV-Delta 2",
        .video_inputs   = 5,
@@ -920,6 +966,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Zoltrix Genie TV/FM",
        .video_inputs   = 3,
@@ -932,6 +979,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = 21,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Terratec TV/Radio+",
        .video_inputs   = 3,
@@ -945,6 +993,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_35,
        .tuner_type     = 1,
+       .tuner_addr     = ADDR_UNSET,
        .has_radio      = 1,
 },{
 
@@ -960,6 +1009,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "IODATA GV-BCTV3/PCI",
        .video_inputs   = 3,
@@ -972,6 +1022,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_ALPS_TSHC6_NTSC,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = gvbctv3pci_audio,
 },{
        .name           = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
@@ -986,6 +1037,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL_I,
+       .tuner_addr     = ADDR_UNSET,
        .has_remote     = 1,
        /* GPIO wiring: (different from Rev.4C !)
                GPIO17: U4.A0 (first hef4052bt)
@@ -994,8 +1046,8 @@ struct tvcard bttv_tvcards[] = {
                GPIO21: U4.nEN
                GPIO22: BT832 Reset Line
                GPIO23: A5,A0, U5,nEN
-          Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
-        */
+       Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
+       */
 },{
        .name           = "Eagle Wireless Capricorn2 (bt878A)",
        .video_inputs   = 4,
@@ -1007,6 +1059,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 1, 2, 3, 4},
        .pll            = PLL_28,
        .tuner_type     = -1 /* TUNER_ALPS_TMDH2_NTSC */,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x34 ---------------------------------- */
@@ -1020,20 +1073,21 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 2, 3, 1, 1},
        .audiomux       = { 1, 0xd0001, 0, 0, 10},
                        /* sound path (5 sources):
-                          MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
+                       MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
                                0= ext. Audio IN
                                1= from MUX2
                                2= Mono TV sound from Tuner
                                3= not connected
-                          MUX2 (mask 0x30000):
+                       MUX2 (mask 0x30000):
                                0,2,3= from MSP34xx
                                1= FM stereo Radio from Tuner */
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Claas Langbehn <claas@bigfoot.com>,
-          Sven Grothklags <sven@upb.de> */
+       Sven Grothklags <sven@upb.de> */
        .name           = "Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS",
        .video_inputs   = 4,
        .audio_inputs   = 3,
@@ -1045,10 +1099,11 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .has_radio      = 1,
 },{
        /* Tim Röstermundt <rosterm@uni-muenster.de>
-          in de.comp.os.unix.linux.hardware:
+       in de.comp.os.unix.linux.hardware:
                options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
                audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
                options tuner type=5 */
@@ -1060,15 +1115,16 @@ struct tvcard bttv_tvcards[] = {
        .gpiomask       = 0x18e0,
        .muxsel         = { 2, 3, 1, 1},
        .audiomux       = { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
-                      /* For cards with tda9820/tda9821:
-                         0x0000: Tuner normal stereo
-                         0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
-                         0x0880: Tuner A2 stereo */
+               /* For cards with tda9820/tda9821:
+                       0x0000: Tuner normal stereo
+                       0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
+                       0x0880: Tuner A2 stereo */
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Miguel Angel Alvarez <maacruz@navegalia.com>
-          old Easy TV BT848 version (model CPH031) */
+       old Easy TV BT848 version (model CPH031) */
        .name           = "Askey CPH031/ BESTBUY Easy TV",
        .video_inputs   = 4,
        .audio_inputs   = 1,
@@ -1080,6 +1136,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = TUNER_TEMIC_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x38 ---------------------------------- */
@@ -1094,10 +1151,11 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
        .pll            = PLL_28,
        .tuner_type     = 5,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* This is the ultimate cheapo capture card
-        * just a BT848A on a small PCB!
-        * Steve Hosgood <steve@equiinet.com> */
+       * just a BT848A on a small PCB!
+       * Steve Hosgood <steve@equiinet.com> */
        .name           = "GrandTec 'Grand Video Capture' (Bt848)",
        .video_inputs   = 2,
        .audio_inputs   = 0,
@@ -1110,19 +1168,21 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_35,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
-        /* Daniel Herrington <daniel.herrington@home.com> */
-        .name           = "Askey CPH060/ Phoebe TV Master Only (No FM)",
-        .video_inputs   = 3,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 0xe00,
-        .muxsel         = { 2, 3, 1, 1},
-        .audiomux       = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
-        .needs_tvaudio  = 1,
-        .pll            = PLL_28,
-        .tuner_type     = TUNER_TEMIC_4036FY5_NTSC,
+       /* Daniel Herrington <daniel.herrington@home.com> */
+       .name           = "Askey CPH060/ Phoebe TV Master Only (No FM)",
+       .video_inputs   = 3,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0xe00,
+       .muxsel         = { 2, 3, 1, 1},
+       .audiomux       = { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = TUNER_TEMIC_4036FY5_NTSC,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Matti Mottus <mottus@physic.ut.ee> */
        .name           = "Askey CPH03x TV Capturer",
@@ -1130,11 +1190,12 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 1,
        .tuner          = 0,
        .svhs           = 2,
-        .gpiomask       = 0x03000F,
+       .gpiomask       = 0x03000F,
        .muxsel         = { 2, 3, 1, 0},
-        .audiomux       = { 2,0,0,0,1 },
+       .audiomux       = { 2,0,0,0,1 },
        .pll            = PLL_28,
        .tuner_type     = 0,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x3c ---------------------------------- */
@@ -1149,7 +1210,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 2, 0, 0, 1, 8},
        .pll            = PLL_35,
        .tuner_type     = TUNER_TEMIC_PAL,
-
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Adrian Cox <adrian@humboldt.co.uk */
        .name           = "AG Electronics GMV1",
@@ -1164,10 +1225,11 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Miguel Angel Alvarez <maacruz@navegalia.com>
-          new Easy TV BT878 version (model CPH061)
-          special thanks to Informatica Mieres for providing the card */
+       new Easy TV BT878 version (model CPH061)
+       special thanks to Informatica Mieres for providing the card */
        .name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
        .video_inputs   = 3,
        .audio_inputs   = 2,
@@ -1179,6 +1241,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Lukas Gebauer <geby@volny.cz> */
        .name           = "ATI TV-Wonder",
@@ -1191,6 +1254,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0xbffe, 0, 0xbfff, 0, 0xbffe},
        .pll            = PLL_28,
        .tuner_type     = TUNER_TEMIC_4006FN5_MULTI_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x40 ---------------------------------- */
@@ -1206,6 +1270,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_TEMIC_4006FN5_MULTI_PAL,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* DeeJay <deejay@westel900.net (2000S) */
        .name           = "Lifeview FlyVideo 2000S LR90",
@@ -1216,7 +1281,7 @@ struct tvcard bttv_tvcards[] = {
        .gpiomask       = 0x18e0,
        .muxsel         = { 2, 3, 0, 1},
                        /* Radio changed from 1e80 to 0x800 to make
-                          FlyVideo2000S in .hu happy (gm)*/
+                       FlyVideo2000S in .hu happy (gm)*/
                        /* -dk-???: set mute=0x1800 for tda9874h daughterboard */
        .audiomux       = { 0x0000,0x0800,0x1000,0x1000,0x1800, 0x1080 },
        .audio_hook     = fv2000s_audio,
@@ -1225,6 +1290,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = 5,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "Terratec TValueRadio",
        .video_inputs   = 3,
@@ -1237,6 +1303,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .has_radio      = 1,
 },{
        /* TANAKA Kei <peg00625@nifty.com> */
@@ -1251,25 +1318,27 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_SHARP_2U5JF5540_NTSC,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = gvbctv3pci_audio,
 },{
 
 /* ---- card 0x44 ---------------------------------- */
-        .name           = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
-       // try "insmod msp3400 simple=0" if you have
-       // sound problems with this card.
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = -1,
-        .gpiomask       = 0x4f8a00,
-       // 0x100000: 1=MSP enabled (0=disable again)
-       // 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC)
-        .audiomux       = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
-       // tvtuner, radio,   external,internal, mute,  stereo
-       /* tuner, Composit, SVid, Composit-on-Svid-adapter*/
-        .muxsel         = { 2, 3 ,0 ,1},
-        .tuner_type     = TUNER_MT2032,
+       .name           = "3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)",
+       /* try "insmod msp3400 simple=0" if you have
+       * sound problems with this card. */
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = -1,
+       .gpiomask       = 0x4f8a00,
+       /* 0x100000: 1=MSP enabled (0=disable again)
+       * 0x010000: Connected to "S0" on tda9880 (0=Pal/BG, 1=NTSC) */
+       .audiomux       = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
+       /* tvtuner, radio,   external,internal, mute,  stereo
+       * tuner, Composit, SVid, Composit-on-Svid-adapter */
+       .muxsel         = { 2, 3 ,0 ,1},
+       .tuner_type     = TUNER_MT2032,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_28,
        .has_radio      = 1,
 },{
@@ -1279,22 +1348,24 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 0,
        .tuner          = -1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_28,
        .muxsel         = { 2 },
        .gpiomask       = 0
 },{
-        /* Tomasz Pyra <hellfire@sedez.iq.pl> */
-        .name           = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
-        .video_inputs   = 3,
-        .audio_inputs   = 4,
-        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 15,
-        .muxsel         = { 2, 3, 1, 1},
-        .audiomux       = { 0, 0, 11, 7, 13, 0}, // TV and Radio with same GPIO !
-        .needs_tvaudio  = 1,
-        .pll            = PLL_28,
-        .tuner_type     = 25,
+       /* Tomasz Pyra <hellfire@sedez.iq.pl> */
+       .name           = "Prolink Pixelview PV-BT878P+ (Rev.4C,8E)",
+       .video_inputs   = 3,
+       .audio_inputs   = 4,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 15,
+       .muxsel         = { 2, 3, 1, 1},
+       .audiomux       = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = 25,
+       .tuner_addr     = ADDR_UNSET,
        .has_remote     = 1,
        /* GPIO wiring:
                GPIO0: U4.A0 (hef4052bt)
@@ -1302,16 +1373,18 @@ struct tvcard bttv_tvcards[] = {
                GPIO2: U4.A1 (second hef4052bt)
                GPIO3: U4.nEN, U5.A0, A5.nEN
                GPIO8-15: vrd866b ?
-        */
+       */
 },{
        .name           = "Lifeview FlyVideo 98EZ (capture only) LR51",
        .video_inputs   = 4,
        .audio_inputs   = 0,
        .tuner          = -1,
        .svhs           = 2,
-       .muxsel         = { 2, 3, 1, 1}, // AV1, AV2, SVHS, CVid adapter on SVHS
+       .muxsel         = { 2, 3, 1, 1}, /* AV1, AV2, SVHS, CVid adapter on SVHS */
        .pll            = PLL_28,
        .no_msp34xx     = 1,
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
 /* ---- card 0x48 ---------------------------------- */
@@ -1329,8 +1402,9 @@ struct tvcard bttv_tvcards[] = {
        .no_tda9875     = 1,
        .pll            = PLL_28,
        .tuner_type     = 5,
-       .audio_hook     = pvbt878p9b_audio, // Note: not all cards have stereo
-       .has_radio      = 1,  // Note: not all cards have radio
+       .tuner_addr     = ADDR_UNSET,
+       .audio_hook     = pvbt878p9b_audio, /* Note: not all cards have stereo */
+       .has_radio      = 1,  /* Note: not all cards have radio */
        .has_remote     = 1,
        /* GPIO wiring:
                GPIO0: A0 hef4052
@@ -1338,7 +1412,7 @@ struct tvcard bttv_tvcards[] = {
                GPIO3: nEN hef4052
                GPIO8-15: vrd866b
                GPIO20,22,23: R30,R29,R28
-        */
+       */
 },{
        /* Clay Kunz <ckunz@mail.arc.nasa.gov> */
        /* you must jumper JP5 for the card to work */
@@ -1352,6 +1426,7 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 0 },
        .needs_tvaudio  = 0,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Miguel Freitas <miguel@cetuc.puc-rio.br> */
        .name           = "RemoteVision MX (RV605)",
@@ -1362,71 +1437,78 @@ struct tvcard bttv_tvcards[] = {
        .gpiomask       = 0x00,
        .gpiomask2      = 0x07ff,
        .muxsel         = { 0x33, 0x13, 0x23, 0x43, 0xf3, 0x73, 0xe3, 0x03,
-                         0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
+                       0xd3, 0xb3, 0xc3, 0x63, 0x93, 0x53, 0x83, 0xa3 },
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .muxsel_hook    = rv605_muxsel,
 },{
-        .name           = "Powercolor MTV878/ MTV878R/ MTV878F",
-        .video_inputs   = 3,
-        .audio_inputs   = 2,
+       .name           = "Powercolor MTV878/ MTV878R/ MTV878F",
+       .video_inputs   = 3,
+       .audio_inputs   = 2,
        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 0x1C800F,  // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset
-        .muxsel         = { 2, 1, 1, },
-        .audiomux       = { 0, 1, 2, 2, 4 },
-        .needs_tvaudio  = 0,
-        .tuner_type     = TUNER_PHILIPS_PAL,
+       .svhs           = 2,
+       .gpiomask       = 0x1C800F,  /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
+       .muxsel         = { 2, 1, 1, },
+       .audiomux       = { 0, 1, 2, 2, 4 },
+       .needs_tvaudio  = 0,
+       .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_28,
        .has_radio      = 1,
 },{
 
 /* ---- card 0x4c ---------------------------------- */
-        /* Masaki Suzuki <masaki@btree.org> */
-        .name           = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
-        .video_inputs   = 3,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 0x140007,
-        .muxsel         = { 2, 3, 1, 1 },
-        .audiomux       = { 0, 1, 2, 3, 4, 0 },
-        .tuner_type     = TUNER_PHILIPS_NTSC,
-        .audio_hook     = windvr_audio,
-},{
-        .name           = "GrandTec Multi Capture Card (Bt878)",
-        .video_inputs   = 4,
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .svhs           = -1,
-        .gpiomask       = 0,
-        .muxsel         = { 2, 3, 1, 0 },
-        .audiomux       = { 0 },
-        .needs_tvaudio  = 0,
-        .no_msp34xx     = 1,
-        .pll            = PLL_28,
-        .tuner_type     = -1,
-},{
-        .name           = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
-        .video_inputs   = 4,
-        .audio_inputs   = 3,
-        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 7,
-        .muxsel         = { 2, 3, 1, 1 },   // Tuner, SVid, SVHS, SVid to SVHS connector
-        .audiomux       = { 0 ,0 ,4, 4,4,4},// Yes, this tuner uses the same audio output for TV and FM radio!
-                                         // This card lacks external Audio In, so we mute it on Ext. & Int.
-                                         // The PCB can take a sbx1637/sbx1673, wiring unknown.
-                                         // This card lacks PCI subsystem ID, sigh.
-                                         // audiomux=1: lower volume, 2+3: mute
-                                         // btwincap uses 0x80000/0x80003
-        .needs_tvaudio  = 0,
-        .no_msp34xx     = 1,
-        .pll            = PLL_28,
-        .tuner_type     = 5, // Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
-                          // radio signal strength indicators work fine.
-       .has_radio              = 1,
+       /* Masaki Suzuki <masaki@btree.org> */
+       .name           = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
+       .video_inputs   = 3,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0x140007,
+       .muxsel         = { 2, 3, 1, 1 },
+       .audiomux       = { 0, 1, 2, 3, 4, 0 },
+       .tuner_type     = TUNER_PHILIPS_NTSC,
+       .tuner_addr     = ADDR_UNSET,
+       .audio_hook     = windvr_audio,
+},{
+       .name           = "GrandTec Multi Capture Card (Bt878)",
+       .video_inputs   = 4,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
+       .gpiomask       = 0,
+       .muxsel         = { 2, 3, 1, 0 },
+       .audiomux       = { 0 },
+       .needs_tvaudio  = 0,
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+},{
+       .name           = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
+       .video_inputs   = 4,
+       .audio_inputs   = 3,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 7,
+       .muxsel         = { 2, 3, 1, 1 },   /* Tuner, SVid, SVHS, SVid to SVHS connector */
+       .audiomux       = { 0 ,0 ,4, 4,4,4},/* Yes, this tuner uses the same audio output for TV and FM radio!
+                                       * This card lacks external Audio In, so we mute it on Ext. & Int.
+                                       * The PCB can take a sbx1637/sbx1673, wiring unknown.
+                                       * This card lacks PCI subsystem ID, sigh.
+                                       * audiomux=1: lower volume, 2+3: mute
+                                       * btwincap uses 0x80000/0x80003
+                                       */
+       .needs_tvaudio  = 0,
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = 5,
+       .tuner_addr     = ADDR_UNSET,
+       /* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
+       radio signal strength indicators work fine. */
+       .has_radio      = 1,
        /* GPIO Info:
                GPIO0,1:   HEF4052 A0,A1
                GPIO2:     HEF4052 nENABLE
@@ -1437,25 +1519,27 @@ struct tvcard bttv_tvcards[] = {
                GPIO22,23: ??
                ??       : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/
 },{
-        /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
-        .name           = "DSP Design TCVIDEO",
-        .video_inputs   = 4,
-        .svhs           = -1,
-        .muxsel         = { 2, 3, 1, 0},
-        .pll            = PLL_28,
-        .tuner_type     = -1,
+       /* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
+       .name           = "DSP Design TCVIDEO",
+       .video_inputs   = 4,
+       .svhs           = -1,
+       .muxsel         = { 2, 3, 1, 0},
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
-        /* ---- card 0x50 ---------------------------------- */
+       /* ---- card 0x50 ---------------------------------- */
        .name           = "Hauppauge WinTV PVR",
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .muxsel         = { 2, 0, 1, 1},
-        .needs_tvaudio  = 1,
-        .pll            = PLL_28,
-        .tuner_type     = -1,
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .muxsel         = { 2, 0, 1, 1},
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 
        .gpiomask       = 7,
        .audiomux       = {7},
@@ -1471,6 +1555,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_NTSC_M,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = gvbctv5pci_audio,
        .has_radio      = 1,
 },{
@@ -1482,9 +1567,10 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 3, 2, 0, 1 },
        .pll            = PLL_28,
        .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
        .name           = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
        .video_inputs   = 3,
@@ -1494,9 +1580,10 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 2, 3, 1 },
        .pll            = PLL_28,
        .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
 
        /* ---- card 0x54 ---------------------------------- */
@@ -1508,9 +1595,10 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 3, 1 },
        .pll            = PLL_28,
        .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
        .name           = "Osprey 101/151",       /* 0x1(4|5)-0004-C4 */
        .video_inputs   = 1,
@@ -1520,9 +1608,10 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 0 },
        .pll            = PLL_28,
        .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
        .name           = "Osprey 101/151 w/ svid",  /* 0x(16|17|20)-00C4-C1 */
        .video_inputs   = 2,
@@ -1532,9 +1621,10 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 0, 1 },
        .pll            = PLL_28,
        .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
        .name           = "Osprey 200/201/250/251",  /* 0x1(8|9|E|F)-0004-C4 */
        .video_inputs   = 1,
@@ -1543,10 +1633,11 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = -1,
        .muxsel         = { 0 },
        .pll            = PLL_28,
-       .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
 
        /* ---- card 0x58 ---------------------------------- */
@@ -1557,10 +1648,11 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 1,
        .muxsel         = { 0, 1 },
        .pll            = PLL_28,
-       .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
        .name           = "Osprey 210/220",   /* 0x1(A|B)-04C0-C1 */
        .video_inputs   = 2,
@@ -1569,10 +1661,11 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 1,
        .muxsel         = { 2, 3 },
        .pll            = PLL_28,
-       .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
        .name           = "Osprey 500",   /* 500 */
        .video_inputs   = 2,
@@ -1582,19 +1675,21 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 2, 3 },
        .pll            = PLL_28,
        .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
-       .name           = "Osprey 540",   /* 540 */
-       .video_inputs   = 4,
-       .audio_inputs   = 1,
-       .tuner          = -1,
-       .pll            = PLL_28,
-       .tuner_type     = -1,
-       .no_msp34xx     = 1,
-       .no_tda9875     = 1,
-       .no_tda7432     = 1,
+       .name           = "Osprey 540",   /* 540 */
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = -1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
 },{
 
        /* ---- card 0x5C ---------------------------------- */
@@ -1605,10 +1700,11 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 1,
        .muxsel         = { 2, 3 },
        .pll            = PLL_28,
-       .tuner_type     = -1,
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
 },{
        /* M G Berberich <berberic@forwiss.uni-passau.de> */
        .name           = "IDS Eagle",
@@ -1616,6 +1712,7 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 0,
        .tuner          = -1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .svhs           = -1,
        .gpiomask       = 0,
        .muxsel         = { 0, 1, 2, 3 },
@@ -1630,6 +1727,7 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 1,
        .tuner          = -1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
        .no_tda7432     = 1,
@@ -1641,38 +1739,40 @@ struct tvcard bttv_tvcards[] = {
        .no_gpioirq     = 1,
        .has_dvb        = 1,
 },{
-        .name           = "Formac ProTV II (bt878)",
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 3,
-        .gpiomask       = 2,
-       // TV, Comp1, Composite over SVID con, SVID
-        .muxsel         = { 2, 3, 1, 1},
-        .audiomux       = { 2, 2, 0, 0, 0 },
-        .pll            = PLL_28,
+       .name           = "Formac ProTV II (bt878)",
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 3,
+       .gpiomask       = 2,
+       /* TV, Comp1, Composite over SVID con, SVID */
+       .muxsel         = { 2, 3, 1, 1},
+       .audiomux       = { 2, 2, 0, 0, 0 },
+       .pll            = PLL_28,
        .has_radio      = 1,
-        .tuner_type     = TUNER_PHILIPS_PAL,
-      /* sound routing:
-           GPIO=0x00,0x01,0x03: mute (?)
-              0x02: both TV and radio (tuner: FM1216/I)
-         The card has onboard audio connectors labeled "cdrom" and "board",
-        not soldered here, though unknown wiring.
-         Card lacks: external audio in, pci subsystem id.
-       */
+       .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
+/* sound routing:
+       GPIO=0x00,0x01,0x03: mute (?)
+       0x02: both TV and radio (tuner: FM1216/I)
+       The card has onboard audio connectors labeled "cdrom" and "board",
+       not soldered here, though unknown wiring.
+       Card lacks: external audio in, pci subsystem id.
+*/
 },{
 
        /* ---- card 0x60 ---------------------------------- */
        .name           = "MachTV",
-        .video_inputs   = 3,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = -1,
-        .gpiomask       = 7,
-        .muxsel         = { 2, 3, 1, 1},
-        .audiomux       = { 0, 1, 2, 3, 4},
-        .needs_tvaudio  = 1,
-        .tuner_type     = 5,
+       .video_inputs   = 3,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = -1,
+       .gpiomask       = 7,
+       .muxsel         = { 2, 3, 1, 1},
+       .audiomux       = { 0, 1, 2, 3, 4},
+       .needs_tvaudio  = 1,
+       .tuner_type     = 5,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = 1,
 },{
        .name           = "Euresys Picolo",
@@ -1686,6 +1786,8 @@ struct tvcard bttv_tvcards[] = {
        .no_tda7432     = 1,
        .muxsel         = { 2, 0, 1},
        .pll            = PLL_28,
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Luc Van Hoeylandt <luc@e-magic.be> */
        .name           = "ProVideo PV150", /* 0x4f */
@@ -1699,7 +1801,8 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .no_msp34xx     = 1,
        .pll            = PLL_28,
-       .tuner_type     = -1,
+       .tuner_type     = UNSET,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Hiroshi Takekawa <sian@big.or.jp> */
        /* This card lacks subsystem ID */
@@ -1716,78 +1819,85 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = 2,
+       .tuner_addr     = ADDR_UNSET,
        .audio_hook     = adtvk503_audio,
 },{
 
        /* ---- card 0x64 ---------------------------------- */
-        .name           = "Hercules Smart TV Stereo",
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 0x00,
-        .muxsel         = { 2, 3, 1, 1 },
-        .needs_tvaudio  = 1,
-        .no_msp34xx     = 1,
-        .pll            = PLL_28,
-        .tuner_type     = 5,
+       .name           = "Hercules Smart TV Stereo",
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0x00,
+       .muxsel         = { 2, 3, 1, 1 },
+       .needs_tvaudio  = 1,
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = 5,
+       .tuner_addr     = ADDR_UNSET,
        /* Notes:
-          - card lacks subsystem ID
-          - stereo variant w/ daughter board with tda9874a @0xb0
-          - Audio Routing:
+       - card lacks subsystem ID
+       - stereo variant w/ daughter board with tda9874a @0xb0
+       - Audio Routing:
                always from tda9874 independent of GPIO (?)
                external line in: unknown
-          - Other chips: em78p156elp @ 0x96 (probably IR remote control)
-                     hef4053 (instead 4052) for unknown function
+       - Other chips: em78p156elp @ 0x96 (probably IR remote control)
+               hef4053 (instead 4052) for unknown function
+       */
+},{
+       .name           = "Pace TV & Radio Card",
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .muxsel         = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */
+       .gpiomask       = 0,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .tuner_type     = 1,
+       .tuner_addr     = ADDR_UNSET,
+       .has_radio      = 1,
+       .pll            = PLL_28,
+       /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
+       only internal line out: (4pin header) RGGL
+       Radio must be decoded by msp3410d (not routed through)*/
+       /*
+       .digital_mode   = DIGITAL_MODE_CAMERA,  todo!
        */
 },{
-        .name           = "Pace TV & Radio Card",
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .muxsel         = { 2, 3, 1, 1}, // Tuner, CVid, SVid, CVid over SVid connector
-        .gpiomask       = 0,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
-        .tuner_type     = 1,
-        .has_radio      = 1,
-        .pll            = PLL_28,
-        /* Bt878, Bt832, FI1246 tuner; no pci subsystem id
-           only internal line out: (4pin header) RGGL
-           Radio must be decoded by msp3410d (not routed through)*/
-        //         .digital_mode   = DIGITAL_MODE_CAMERA, // todo!
-},{
-        /* Chris Willing <chris@vislab.usyd.edu.au> */
-        .name           = "IVC-200",
-        .video_inputs   = 1,
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .tuner_type     = -1,
-        .svhs           = -1,
-        .gpiomask       = 0xdf,
-        .muxsel         = { 2 },
-        .pll            = PLL_28,
+       /* Chris Willing <chris@vislab.usyd.edu.au> */
+       .name           = "IVC-200",
+       .video_inputs   = 1,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+       .svhs           = -1,
+       .gpiomask       = 0xdf,
+       .muxsel         = { 2 },
+       .pll            = PLL_28,
 },{
        .name           = "Grand X-Guard / Trust 814PCI",
        .video_inputs   = 16,
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .svhs           = -1,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
        .tuner_type     = 4,
-        .gpiomask2      = 0xff,
+       .tuner_addr     = ADDR_UNSET,
+       .gpiomask2      = 0xff,
        .muxsel         = { 2,2,2,2, 3,3,3,3, 1,1,1,1, 0,0,0,0 },
        .muxsel_hook    = xguard_muxsel,
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
-        .no_tda7432     = 1,
+       .no_tda7432     = 1,
        .pll            = PLL_28,
 },{
 
        /* ---- card 0x68 ---------------------------------- */
        .name           = "Nebula Electronics DigiTV",
        .video_inputs   = 1,
-        .tuner          = -1,
+       .tuner          = -1,
        .svhs           = -1,
        .muxsel         = { 2, 3, 1, 0},
        .no_msp34xx     = 1,
@@ -1795,22 +1905,24 @@ struct tvcard bttv_tvcards[] = {
        .no_tda7432     = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .has_dvb        = 1,
        .no_gpioirq     = 1,
 },{
        /* Jorge Boncompte - DTI2 <jorge@dti2.net> */
        .name           = "ProVideo PV143",
-        .video_inputs   = 4,
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .svhs           = -1,
-        .gpiomask       = 0,
-        .muxsel         = { 2, 3, 1, 0 },
-        .audiomux       = { 0 },
-        .needs_tvaudio  = 0,
-        .no_msp34xx     = 1,
-        .pll            = PLL_28,
-        .tuner_type     = -1,
+       .video_inputs   = 4,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
+       .gpiomask       = 0,
+       .muxsel         = { 2, 3, 1, 0 },
+       .audiomux       = { 0 },
+       .needs_tvaudio  = 0,
+       .no_msp34xx     = 1,
+       .pll            = PLL_28,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* M.Klahr@phytec.de */
        .name           = "PHYTEC VD-009-X1 MiniDIN (bt878)",
@@ -1824,6 +1936,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "PHYTEC VD-009-X1 Combi (bt878)",
        .video_inputs   = 4,
@@ -1836,6 +1949,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
 
        /* ---- card 0x6c ---------------------------------- */
@@ -1846,13 +1960,14 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 9,
        .gpiomask       = 0x00,
        .gpiomask2      = 0x03, /* gpiomask2 defines the bits used to switch audio
-                                  via the upper nibble of muxsel. here: used for
-                                  xternal video-mux */
+                               via the upper nibble of muxsel. here: used for
+                               xternal video-mux */
        .muxsel         = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x00 },
        .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        .name           = "PHYTEC VD-009 Combi (bt878)",
        .video_inputs   = 10,
@@ -1861,23 +1976,25 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 9,
        .gpiomask       = 0x00,
        .gpiomask2      = 0x03, /* gpiomask2 defines the bits used to switch audio
-                                  via the upper nibble of muxsel. here: used for
-                                  xternal video-mux */
+                               via the upper nibble of muxsel. here: used for
+                               xternal video-mux */
        .muxsel         = { 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 0x01, 0x01 },
        .audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
        .needs_tvaudio  = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
-        .name           = "IVC-100",
-        .video_inputs   = 4,
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .tuner_type     = -1,
-        .svhs           = -1,
-        .gpiomask       = 0xdf,
-        .muxsel         = { 2, 3, 1, 0 },
-        .pll            = PLL_28,
+       .name           = "IVC-100",
+       .video_inputs   = 4,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+       .svhs           = -1,
+       .gpiomask       = 0xdf,
+       .muxsel         = { 2, 3, 1, 0 },
+       .pll            = PLL_28,
 },{
        /* IVC-120G - Alan Garfield <alan@fromorbit.com> */
        .name           = "IVC-120G",
@@ -1885,6 +2002,7 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 0,    /* card has no audio */
        .tuner          = -1,   /* card has no tuner */
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .svhs           = -1,   /* card has no svhs */
        .needs_tvaudio  = 0,
        .no_msp34xx     = 1,
@@ -1892,7 +2010,7 @@ struct tvcard bttv_tvcards[] = {
        .no_tda7432     = 1,
        .gpiomask       = 0x00,
        .muxsel         = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-                           0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
+                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
        .muxsel_hook    = ivc120_muxsel,
        .pll            = PLL_28,
 },{
@@ -1905,6 +2023,7 @@ struct tvcard bttv_tvcards[] = {
        .svhs           = 2,
        .muxsel         = { 2, 3, 1, 0},
        .tuner_type     = TUNER_PHILIPS_ATSC,
+       .tuner_addr     = ADDR_UNSET,
        .has_dvb        = 1,
 },{
        .name           = "Twinhan DST + clones",
@@ -1912,19 +2031,21 @@ struct tvcard bttv_tvcards[] = {
        .no_tda9875     = 1,
        .no_tda7432     = 1,
        .tuner_type     = TUNER_ABSENT,
+       .tuner_addr     = ADDR_UNSET,
        .no_video       = 1,
        .has_dvb        = 1,
 },{
-        .name           = "Winfast VC100",
+       .name           = "Winfast VC100",
        .video_inputs   = 3,
        .audio_inputs   = 0,
        .svhs           = 1,
-       .tuner          = -1, // no tuner
-       .muxsel         = { 3, 1, 1, 3}, // Vid In, SVid In, Vid over SVid in connector
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
-        .tuner_type     = TUNER_ABSENT,
+       .tuner          = -1,
+       .muxsel         = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .tuner_type     = TUNER_ABSENT,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_28,
 },{
        .name           = "Teppro TEV-560/InterVision IV-560",
@@ -1937,44 +2058,49 @@ struct tvcard bttv_tvcards[] = {
        .audiomux       = { 1, 1, 1, 1, 0},
        .needs_tvaudio  = 1,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .pll            = PLL_35,
 },{
 
        /* ---- card 0x74 ---------------------------------- */
-        .name           = "SIMUS GVC1100",
-        .video_inputs   = 4,
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .svhs           = -1,
-        .tuner_type     = -1,
-        .pll            = PLL_28,
-        .muxsel         = { 2, 2, 2, 2},
-        .gpiomask       = 0x3F,
+       .name           = "SIMUS GVC1100",
+       .video_inputs   = 4,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+       .pll            = PLL_28,
+       .muxsel         = { 2, 2, 2, 2},
+       .gpiomask       = 0x3F,
        .muxsel_hook    = gvc1100_muxsel,
 },{
-        /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
-        .name           = "NGS NGSTV+",
-        .video_inputs   = 3,
-        .tuner          = 0,
-        .svhs           = 2,
-        .gpiomask       = 0x008007,
-        .muxsel         = {2, 3, 0, 0},
-        .audiomux       = {0, 0, 0, 0, 0x000003, 0},
-        .pll            = PLL_28,
-        .tuner_type     = TUNER_PHILIPS_PAL,
-        .has_remote     = 1,
-},{
-        /* http://linuxmedialabs.com */
-        .name           = "LMLBT4",
-        .video_inputs   = 4, /* IN1,IN2,IN3,IN4 */
-        .audio_inputs   = 0,
-        .tuner          = -1,
-        .svhs           = -1,
-        .muxsel         = { 2, 3, 1, 0 },
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
-        .needs_tvaudio  = 0,
+       /* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
+       .name           = "NGS NGSTV+",
+       .video_inputs   = 3,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0x008007,
+       .muxsel         = {2, 3, 0, 0},
+       .audiomux       = {0, 0, 0, 0, 0x000003, 0},
+       .pll            = PLL_28,
+       .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
+       .has_remote     = 1,
+},{
+       /* http://linuxmedialabs.com */
+       .name           = "LMLBT4",
+       .video_inputs   = 4, /* IN1,IN2,IN3,IN4 */
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
+       .muxsel         = { 2, 3, 1, 0 },
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .needs_tvaudio  = 0,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Helmroos Harri <harri.helmroos@pp.inet.fi> */
        .name           = "Tekram M205 PRO",
@@ -1982,6 +2108,7 @@ struct tvcard bttv_tvcards[] = {
        .audio_inputs   = 1,
        .tuner          = 0,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .svhs           = 2,
        .needs_tvaudio  = 0,
        .gpiomask       = 0x68,
@@ -2004,6 +2131,7 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .has_remote     = 1,
        .has_radio      = 1,
 },{
@@ -2026,6 +2154,8 @@ struct tvcard bttv_tvcards[] = {
        .pll            = PLL_28,
        .needs_tvaudio  = 0,
        .muxsel_hook    = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Spirit TV Tuner from http://spiritmodems.com.au */
        /* Stafford Goodsell <surge@goliath.homeunix.org> */
@@ -2038,23 +2168,25 @@ struct tvcard bttv_tvcards[] = {
        .muxsel         = { 2, 1, 1 },
        .audiomux       = { 0x02, 0x00, 0x00, 0x00, 0x00},
        .tuner_type     = TUNER_TEMIC_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
 },{
        /* Wolfram Joost <wojo@frokaschwei.de> */
-        .name           = "AVerMedia AVerTV DVB-T 771",
-        .video_inputs   = 2,
-        .svhs           = 1,
-        .tuner          = -1,
-        .tuner_type     = TUNER_ABSENT,
-        .muxsel         = { 3 , 3 },
-        .no_msp34xx     = 1,
-        .no_tda9875     = 1,
-        .no_tda7432     = 1,
-        .pll            = PLL_28,
-        .has_dvb        = 1,
-        .no_gpioirq     = 1,
-        .has_remote     = 1,
+       .name           = "AVerMedia AVerTV DVB-T 771",
+       .video_inputs   = 2,
+       .svhs           = 1,
+       .tuner          = -1,
+       .tuner_type     = TUNER_ABSENT,
+       .tuner_addr     = ADDR_UNSET,
+       .muxsel         = { 3 , 3 },
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .pll            = PLL_28,
+       .has_dvb        = 1,
+       .no_gpioirq     = 1,
+       .has_remote     = 1,
 },{
        /* ---- card 0x7c ---------------------------------- */
        /* Matt Jesson <dvb@jesson.eclipse.co.uk> */
@@ -2069,6 +2201,7 @@ struct tvcard bttv_tvcards[] = {
        .no_tda7432     = 1,
        .pll            = PLL_28,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .has_dvb        = 1,
        .no_gpioirq     = 1,
        .has_remote     = 1,
@@ -2081,12 +2214,13 @@ struct tvcard bttv_tvcards[] = {
        .svhs             = -1,
        .gpiomask         = 0x0,
        .muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
-                             3, 3, 3, 3, 3, 3, 3, 3 },
+                       3, 3, 3, 3, 3, 3, 3, 3 },
        .muxsel_hook      = sigmaSQ_muxsel,
        .audiomux         = { 0 },
        .no_msp34xx       = 1,
        .pll              = PLL_28,
        .tuner_type       = -1,
+       .tuner_addr       = ADDR_UNSET,
 },{
        /* andre.schwarz@matrix-vision.de */
        .name             = "MATRIX Vision Sigma-SLC",
@@ -2101,6 +2235,7 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx       = 1,
        .pll              = PLL_28,
        .tuner_type       = -1,
+       .tuner_addr       = ADDR_UNSET,
 },{
        /* BTTV_APAC_VIEWCOMP */
        /* Attila Kondoros <attila.kondoros@chello.hu> */
@@ -2116,13 +2251,14 @@ struct tvcard bttv_tvcards[] = {
        .needs_tvaudio  = 0,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_PAL,
+       .tuner_addr     = ADDR_UNSET,
        .has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
        .has_radio      = 1,   /* not every card has radio */
 },{
 
        /* ---- card 0x80 ---------------------------------- */
        /* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
-       .name           = "DVICO FusionHDTV DVB-T Lite",
+       .name           = "DViCO FusionHDTV DVB-T Lite",
        .tuner          = -1,
        .no_msp34xx     = 1,
        .no_tda9875     = 1,
@@ -2131,6 +2267,7 @@ struct tvcard bttv_tvcards[] = {
        .no_video       = 1,
        .has_dvb        = 1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
 },{
        /* Steven <photon38@pchome.com.tw> */
        .name           = "V-Gear MyVCD",
@@ -2144,62 +2281,65 @@ struct tvcard bttv_tvcards[] = {
        .no_msp34xx     = 1,
        .pll            = PLL_28,
        .tuner_type     = TUNER_PHILIPS_NTSC_M,
+       .tuner_addr     = ADDR_UNSET,
        .has_radio      = 0,
-       // .has_remote     = 1,
 },{
        /* Rick C <cryptdragoon@gmail.com> */
-        .name           = "Super TV Tuner",
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .muxsel         = { 2, 3, 1, 0},
-        .tuner_type     = TUNER_PHILIPS_NTSC,
-        .gpiomask       = 0x008007,
-        .audiomux       = { 0, 0x000001,0,0, 0},
-        .needs_tvaudio  = 1,
-        .has_radio      = 1,
-},{
-               /* Chris Fanning <video4linux@haydon.net> */
-               .name           = "Tibet Systems 'Progress DVR' CS16",
-               .video_inputs   = 16,
-               .audio_inputs   = 0,
-               .tuner          = -1,
-               .svhs           = -1,
-               .muxsel         = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
-               .pll            = PLL_28,
-               .no_msp34xx     = 1,
-               .no_tda9875     = 1,
-               .no_tda7432     = 1,
-               .tuner_type     = -1,
-               .muxsel_hook    = tibetCS16_muxsel,
+       .name           = "Super TV Tuner",
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .muxsel         = { 2, 3, 1, 0},
+       .tuner_type     = TUNER_PHILIPS_NTSC,
+       .tuner_addr     = ADDR_UNSET,
+       .gpiomask       = 0x008007,
+       .audiomux       = { 0, 0x000001,0,0, 0},
+       .needs_tvaudio  = 1,
+       .has_radio      = 1,
+},{
+       /* Chris Fanning <video4linux@haydon.net> */
+       .name           = "Tibet Systems 'Progress DVR' CS16",
+       .video_inputs   = 16,
+       .audio_inputs   = 0,
+       .tuner          = -1,
+       .svhs           = -1,
+       .muxsel         = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+       .pll            = PLL_28,
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+       .muxsel_hook    = tibetCS16_muxsel,
 },
 {
        /* Bill Brack <wbrack@mmm.com.hk> */
        /*
-        * Note that, because of the card's wiring, the "master"
-        * BT878A chip (i.e. the one which controls the analog switch
-        * and must use this card type) is the 2nd one detected.  The
-        * other 3 chips should use card type 0x85, whose description
-        * follows this one.  There is a EEPROM on the card (which is
-        * connected to the I2C of one of those other chips), but is
-        * not currently handled.  There is also a facility for a
-        * "monitor", which is also not currently implemented.
-        */
-       .name           = "Kodicom 4400R (master)",
+       * Note that, because of the card's wiring, the "master"
+       * BT878A chip (i.e. the one which controls the analog switch
+       * and must use this card type) is the 2nd one detected.  The
+       * other 3 chips should use card type 0x85, whose description
+       * follows this one.  There is a EEPROM on the card (which is
+       * connected to the I2C of one of those other chips), but is
+       * not currently handled.  There is also a facility for a
+       * "monitor", which is also not currently implemented.
+       */
+       .name           = "Kodicom 4400R (master)",
        .video_inputs   = 16,
        .audio_inputs   = 0,
        .tuner          = -1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .svhs           = -1,
        /* GPIO bits 0-9 used for analog switch:
-        *   00 - 03:   camera selector
-        *   04 - 06:   channel (controller) selector
-        *   07:        data (1->on, 0->off)
-        *   08:        strobe
-        *   09:        reset
-        * bit 16 is input from sync separator for the channel
-        */
+       *   00 - 03:    camera selector
+       *   04 - 06:    channel (controller) selector
+       *   07: data (1->on, 0->off)
+       *   08: strobe
+       *   09: reset
+       * bit 16 is input from sync separator for the channel
+       */
        .gpiomask       = 0x0003ff,
        .no_gpioirq     = 1,
        .muxsel         = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
@@ -2212,15 +2352,16 @@ struct tvcard bttv_tvcards[] = {
 {
        /* Bill Brack <wbrack@mmm.com.hk> */
        /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
-        * one which controls the analog switch, and must use the card type)
-        * is the 2nd one detected.  The other 3 chips should use this card
-        * type
-        */
+       * one which controls the analog switch, and must use the card type)
+       * is the 2nd one detected.  The other 3 chips should use this card
+       * type
+       */
        .name           = "Kodicom 4400R (slave)",
        .video_inputs   = 16,
        .audio_inputs   = 0,
        .tuner          = -1,
        .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
        .svhs           = -1,
        .gpiomask       = 0x010000,
        .no_gpioirq     = 1,
@@ -2232,18 +2373,51 @@ struct tvcard bttv_tvcards[] = {
        .muxsel_hook    = kodicom4400r_muxsel,
 },
 {
-        /* ---- card 0x85---------------------------------- */
-        /* Michael Henson <mhenson@clarityvi.com> */
-        /* Adlink RTV24 with special unlock codes */
-        .name           = "Adlink RTV24",
-        .video_inputs   = 4,
-        .audio_inputs   = 1,
-        .tuner          = 0,
-        .svhs           = 2,
-        .muxsel         = { 2, 3, 1, 0},
-        .tuner_type     = -1,
-        .pll            = PLL_28,
-
+       /* ---- card 0x86---------------------------------- */
+       /* Michael Henson <mhenson@clarityvi.com> */
+       /* Adlink RTV24 with special unlock codes */
+       .name           = "Adlink RTV24",
+       .video_inputs   = 4,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .muxsel         = { 2, 3, 1, 0},
+       .tuner_type     = -1,
+       .tuner_addr     = ADDR_UNSET,
+       .pll            = PLL_28,
+},
+{
+       /* ---- card 0x87---------------------------------- */
+       /* Michael Krufky <mkrufky@m1k.net> */
+       .name           = "DViCO FusionHDTV 5 Lite",
+       .tuner          = 0,
+       .tuner_type     = TUNER_LG_TDVS_H062F,
+       .tuner_addr     = ADDR_UNSET,
+       .video_inputs   = 2,
+       .audio_inputs   = 1,
+       .svhs           = 2,
+       .muxsel         = { 2, 3 },
+       .gpiomask       = 0x00e00007,
+       .audiomux       = { 0x00400005, 0, 0, 0, 0, 0 },
+       .no_msp34xx     = 1,
+       .no_tda9875     = 1,
+       .no_tda7432     = 1,
+},{
+       /* ---- card 0x88---------------------------------- */
+       /* Mauro Carvalho Chehab <mchehab@brturbo.com.br> */
+       .name           = "Acorp Y878F",
+       .video_inputs   = 3,
+       .audio_inputs   = 1,
+       .tuner          = 0,
+       .svhs           = 2,
+       .gpiomask       = 0x01fe00,
+       .muxsel         = { 2, 3, 1, 1},
+       .audiomux       = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
+       .needs_tvaudio  = 1,
+       .pll            = PLL_28,
+       .tuner_type     = TUNER_YMEC_TVF66T5_B_DFF,
+       .tuner_addr     = 0xc1 >>1,
+       .has_radio      = 1,
 }};
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2355,32 +2529,32 @@ static void flyvideo_gpio(struct bttv *btv)
        int tuner=-1,ttype;
 
        gpio_inout(0xffffff, 0);
-       udelay(8);  // without this we would see the 0x1800 mask
+       udelay(8);  /* without this we would see the 0x1800 mask */
        gpio = gpio_read();
        /* FIXME: must restore OUR_EN ??? */
 
-       // all cards provide GPIO info, some have an additional eeprom
-       // LR50: GPIO coding can be found lower right CP1 .. CP9
-       //       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
-       //       GPIO14-12: n.c.
-       // LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
-
-       // lowest 3 bytes are remote control codes (no handshake needed)
-        // xxxFFF: No remote control chip soldered
-        // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
-       // Note: Some bits are Audio_Mask !
+       /* all cards provide GPIO info, some have an additional eeprom
+        * LR50: GPIO coding can be found lower right CP1 .. CP9
+        *       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
+        *       GPIO14-12: n.c.
+        * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
 
+        * lowest 3 bytes are remote control codes (no handshake needed)
+        * xxxFFF: No remote control chip soldered
+        * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
+        * Note: Some bits are Audio_Mask !
+        */
        ttype=(gpio&0x0f0000)>>16;
        switch(ttype) {
-       case 0x0: tuner=2; // NTSC, e.g. TPI8NSR11P
+       case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */
                break;
-        case 0x2: tuner=39;// LG NTSC (newer TAPC series) TAPC-H701P
+        case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */
                break;
-       case 0x4: tuner=5; // Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216
+       case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
                break;
-       case 0x6: tuner=37; // LG PAL (newer TAPC series) TAPC-G702P
+       case 0x6: tuner=37;/* LG PAL (newer TAPC series) TAPC-G702P */
                break;
-       case 0xC: tuner=3; // Philips SECAM(+PAL) FQ1216ME or FI1216MF
+               case 0xC: tuner=3; /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
                break;
        default:
                printk(KERN_INFO "bttv%d: FlyVideo_gpio: unknown tuner type.\n", btv->c.nr);
@@ -2388,15 +2562,16 @@ static void flyvideo_gpio(struct bttv *btv)
 
        has_remote          =   gpio & 0x800000;
        has_radio           =   gpio & 0x400000;
-       //   unknown                   0x200000;
-       //   unknown2                  0x100000;
-        is_capture_only     = !(gpio & 0x008000); //GPIO15
+       /*   unknown                   0x200000;
+        *   unknown2                  0x100000; */
+        is_capture_only     = !(gpio & 0x008000); /* GPIO15 */
        has_tda9820_tda9821 = !(gpio & 0x004000);
-       is_lr90             = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only)
-        //                     gpio & 0x001000 // output bit for audio routing
+       is_lr90             = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */
+       /*
+        * gpio & 0x001000    output bit for audio routing */
 
        if(is_capture_only)
-               tuner=4; // No tuner present
+               tuner=4; /* No tuner present */
 
        printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
               btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
@@ -2404,15 +2579,15 @@ static void flyvideo_gpio(struct bttv *btv)
                btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
                is_capture_only?"yes":"no ");
 
-       if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through
+       if(tuner!= -1) /* only set if known tuner autodetected, else let insmod option through */
                btv->tuner_type = tuner;
        btv->has_radio = has_radio;
 
-       // LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
-        // LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
-       // Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute
+       /* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
+        * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
+        * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
        if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio;
-       //todo: if(has_tda9874) btv->audio_hook = fv2000s_audio;
+       /* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */
 }
 
 static int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
@@ -2633,6 +2808,8 @@ void __devinit bttv_init_card1(struct bttv *btv)
 void __devinit bttv_init_card2(struct bttv *btv)
 {
        int tda9887;
+       int addr=ADDR_UNSET;
+
         btv->tuner_type = -1;
 
        if (BTTV_UNKNOWN == btv->c.type) {
@@ -2773,9 +2950,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
        btv->pll.pll_current = -1;
 
        /* tuner configuration (from card list / autodetect / insmod option) */
-       if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
+       if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+               addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+       if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
                if(UNSET == btv->tuner_type)
-                       btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
+                       btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
        if (UNSET != tuner[btv->c.nr])
                btv->tuner_type = tuner[btv->c.nr];
        printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type);
@@ -2787,7 +2967,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
 
                tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
                tun_setup.type = btv->tuner_type;
-               tun_setup.addr = ADDR_UNSET;
+               tun_setup.addr = addr;
 
                bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
        }
@@ -2880,7 +3060,7 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
 {
        struct tveeprom tv;
 
-       tveeprom_hauppauge_analog(&tv, eeprom_data);
+       tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
        btv->tuner_type = tv.tuner_type;
        btv->has_radio  = tv.has_radio;
 }
@@ -2902,7 +3082,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv)
        btv->mbox_csel    = 1 << 10;
 
        freq=88000/62.5;
-       tea5757_write(btv, 5 * freq + 0x358); // write 0x1ed8
+       tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
        if (0x1ed8 == tea5757_read(btv)) {
                printk("bttv%d: Terratec Active Radio Upgrade found.\n",
                       btv->c.nr);
@@ -3073,7 +3253,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
               case 0x0060:
               case 0x0070:
                       btv->c.type = BTTV_OSPREY2x0;
-                      //enable output on select control lines
+                      /* enable output on select control lines */
                       gpio_inout(0xffffff,0x000303);
                       break;
               default:
@@ -3105,7 +3285,7 @@ static int tuner_1_table[] = {
         TUNER_TEMIC_NTSC,  TUNER_TEMIC_PAL,
        TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
        TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
-        TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, //TUNER_TEMIC_SECAM
+        TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
         TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
 
 static void __devinit avermedia_eeprom(struct bttv *btv)
@@ -3126,7 +3306,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
 
        if (tuner_make == 4)
                if(tuner_format == 0x09)
-                       tuner = TUNER_LG_NTSC_NEW_TAPC; // TAPC-G702P
+                       tuner = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
 
        printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
                btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
@@ -3143,7 +3323,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
 /* used on Voodoo TV/FM (Voodoo 200), S0 wired to 0x10000 */
 void bttv_tda9880_setnorm(struct bttv *btv, int norm)
 {
-       // fix up our card entry
+       /* fix up our card entry */
        if(norm==VIDEO_MODE_NTSC) {
                bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[0]=0x957fff;
                bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x957fff;
@@ -3154,7 +3334,7 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm)
                 bttv_tvcards[BTTV_VOODOOTV_FM].audiomux[4]=0x947fff;
                dprintk("bttv_tda9880_setnorm to PAL\n");
        }
-       // set GPIO according
+       /* set GPIO according */
        gpio_bits(bttv_tvcards[btv->c.type].gpiomask,
                  bttv_tvcards[btv->c.type].audiomux[btv->audio]);
 }
@@ -3447,7 +3627,7 @@ static int tea5757_read(struct bttv *btv)
        udelay(10);
        timeout= jiffies + HZ;
 
-       // wait for DATA line to go low; error if it doesn't
+       /* wait for DATA line to go low; error if it doesn't */
        while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
                schedule();
        if (bus_in(btv,btv->mbox_data)) {
@@ -3574,8 +3754,8 @@ gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set)
                        con = 0x300;
                if (v->mode & VIDEO_SOUND_STEREO)
                        con = 0x200;
-//             if (v->mode & VIDEO_SOUND_MONO)
-//                     con = 0x100;
+/*             if (v->mode & VIDEO_SOUND_MONO)
+ *                     con = 0x100; */
                gpio_bits(0x300, con);
        } else {
                v->mode = VIDEO_SOUND_STEREO |
@@ -3718,7 +3898,7 @@ lt9415_audio(struct bttv *btv, struct video_audio *v, int set)
         }
 }
 
-// TDA9821 on TerraTV+ Bt848, Bt878
+/* TDA9821 on TerraTV+ Bt848, Bt878 */
 static void
 terratv_audio(struct bttv *btv, struct video_audio *v, int set)
 {
@@ -3818,7 +3998,7 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set)
                }
                if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
                    || (v->mode & VIDEO_SOUND_STEREO)) {
-                       val = 0x1080; //-dk-???: 0x0880, 0x0080, 0x1800 ...
+                       val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
                }
                if (val != 0xffff) {
                        gpio_bits(0x1800, val);
@@ -3869,10 +4049,10 @@ adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
 {
        unsigned int con = 0xffffff;
 
-       //btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN);
+       /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
 
        if (set) {
-               //btor(***, BT848_GPIO_OUT_EN);
+               /* btor(***, BT848_GPIO_OUT_EN); */
                if (v->mode & VIDEO_SOUND_LANG1)
                        con = 0x00000000;
                if (v->mode & VIDEO_SOUND_LANG2)
@@ -4079,14 +4259,14 @@ static void kodicom4400r_init(struct bttv *btv)
        master[btv->c.nr+2] = btv;
 }
 
-// The Grandtec X-Guard framegrabber card uses two Dual 4-channel
-// video multiplexers to provide up to 16 video inputs. These
-// multiplexers are controlled by the lower 8 GPIO pins of the
-// bt878. The multiplexers probably Pericom PI5V331Q or similar.
-
-// xxx0 is pin xxx of multiplexer U5,
-// yyy1 is pin yyy of multiplexer U2
+/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel
+ * video multiplexers to provide up to 16 video inputs. These
+ * multiplexers are controlled by the lower 8 GPIO pins of the
+ * bt878. The multiplexers probably Pericom PI5V331Q or similar.
 
+ * xxx0 is pin xxx of multiplexer U5,
+ * yyy1 is pin yyy of multiplexer U2
+ */
 #define ENA0    0x01
 #define ENB0    0x02
 #define ENA1    0x04
@@ -4157,14 +4337,14 @@ static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
 
 static void ivc120_muxsel(struct bttv *btv, unsigned int input)
 {
-       // Simple maths
+       /* Simple maths */
        int key = input % 4;
        int matrix = input / 4;
 
        dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
                btv->c.nr, input, matrix, key);
 
-       // Handles the input selection on the TDA8540's
+       /* Handles the input selection on the TDA8540's */
        bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
                      ((matrix == 3) ? (key | key << 2) : 0x00), 1);
        bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00,
@@ -4174,17 +4354,17 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input)
        bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
                      ((matrix == 2) ? (key | key << 2) : 0x00), 1);
 
-       // Handles the output enables on the TDA8540's
+       /* Handles the output enables on the TDA8540's */
        bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
-                     ((matrix == 3) ? 0x03 : 0x00), 1);  // 13 - 16
+                     ((matrix == 3) ? 0x03 : 0x00), 1);  /* 13 - 16 */
        bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
-                     ((matrix == 0) ? 0x03 : 0x00), 1);  // 1-4
+                     ((matrix == 0) ? 0x03 : 0x00), 1);  /* 1-4 */
        bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
-                     ((matrix == 1) ? 0x03 : 0x00), 1);  // 5-8
+                     ((matrix == 1) ? 0x03 : 0x00), 1);  /* 5-8 */
        bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
-                     ((matrix == 2) ? 0x03 : 0x00), 1);  // 9-12
+                     ((matrix == 2) ? 0x03 : 0x00), 1);  /* 9-12 */
 
-       // Selects MUX0 for input on the 878
+       /* Selects MUX0 for input on the 878 */
        btaor((0)<<5, ~(3<<5), BT848_IFORM);
 }
 
index 087efb4dea09a4b67a36e21a7a46c28f76c8831a..a564321db2f02039c9e7d6804a2c4d204d2b19c4 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-driver.c,v 1.52 2005/08/04 00:55:16 mchehab Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -42,6 +41,9 @@
 
 #include "bttvp.h"
 
+#include "rds.h"
+
+
 unsigned int bttv_num;                 /* number of Bt848s in use */
 struct bttv bttvs[BTTV_MAX];
 
@@ -3128,15 +3130,12 @@ static int radio_open(struct inode *inode, struct file *file)
 
        dprintk("bttv%d: open called (radio)\n",btv->c.nr);
        down(&btv->lock);
-       if (btv->radio_user) {
-               up(&btv->lock);
-               return -EBUSY;
-       }
+
        btv->radio_user++;
+
        file->private_data = btv;
 
-       i2c_vidiocschan(btv);
-        bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
+       bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
        audio_mux(btv,AUDIO_RADIO);
 
        up(&btv->lock);
@@ -3145,9 +3144,13 @@ static int radio_open(struct inode *inode, struct file *file)
 
 static int radio_release(struct inode *inode, struct file *file)
 {
-       struct bttv    *btv = file->private_data;
+       struct bttv        *btv = file->private_data;
+       struct rds_command cmd;
 
        btv->radio_user--;
+
+       bttv_call_i2c_clients(btv, RDS_CMD_CLOSE, &cmd);
+
        return 0;
 }
 
@@ -3203,13 +3206,42 @@ static int radio_ioctl(struct inode *inode, struct file *file,
        return video_usercopy(inode, file, cmd, arg, radio_do_ioctl);
 }
 
+static ssize_t radio_read(struct file *file, char __user *data,
+                        size_t count, loff_t *ppos)
+{
+       struct bttv    *btv = file->private_data;
+       struct rds_command cmd;
+       cmd.block_count = count/3;
+       cmd.buffer = data;
+       cmd.instance = file;
+       cmd.result = -ENODEV;
+
+       bttv_call_i2c_clients(btv, RDS_CMD_READ, &cmd);
+
+       return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+       struct bttv    *btv = file->private_data;
+       struct rds_command cmd;
+       cmd.instance = file;
+       cmd.event_list = wait;
+       cmd.result = -ENODEV;
+       bttv_call_i2c_clients(btv, RDS_CMD_POLL, &cmd);
+
+       return cmd.result;
+}
+
 static struct file_operations radio_fops =
 {
        .owner    = THIS_MODULE,
        .open     = radio_open,
+       .read     = radio_read,
        .release  = radio_release,
        .ioctl    = radio_ioctl,
        .llseek   = no_llseek,
+       .poll     = radio_poll,
 };
 
 static struct video_device radio_template =
@@ -4047,6 +4079,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
        struct bttv_buffer_set idle;
        unsigned long flags;
 
+       dprintk("bttv%d: suspend %d\n", btv->c.nr, state.event);
 
        /* stop dma + irqs */
        spin_lock_irqsave(&btv->s_lock,flags);
@@ -4079,15 +4112,29 @@ static int bttv_resume(struct pci_dev *pci_dev)
 {
         struct bttv *btv = pci_get_drvdata(pci_dev);
        unsigned long flags;
+       int err;
 
        dprintk("bttv%d: resume\n", btv->c.nr);
 
        /* restore pci state */
        if (btv->state.disabled) {
-               pci_enable_device(pci_dev);
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+                                                               btv->c.nr);
+                       return err;
+               }
                btv->state.disabled = 0;
        }
-       pci_set_power_state(pci_dev, PCI_D0);
+       err=pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               pci_disable_device(pci_dev);
+               printk(KERN_WARNING "bttv%d: Can't enable device.\n",
+                                                       btv->c.nr);
+               btv->state.disabled = 1;
+               return err;
+       }
+
        pci_restore_state(pci_dev);
 
        /* restore bt878 state */
index 77320cdf205fc5e7d6fa03303b0c5b7644597540..6b280c03e398dc7fa5d4db3607847e4cf5db3acd 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-gpio.c,v 1.7 2005/02/16 12:14:10 kraxel Exp $
 
     bttv-gpio.c  --  gpio sub drivers
 
index 706dc48df9625e1741bc9c9029db86b897fe500a..e684df37eb0e249c982b8255ffeb84c814c000d0 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-i2c.c,v 1.25 2005/07/05 17:37:35 nsh Exp $
 
     bttv-i2c.c  --  all the i2c code is here
 
@@ -381,6 +380,7 @@ void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
 }
 
 static char *i2c_devs[128] = {
+       [ 0x1c >> 1 ] = "lgdt330x",
        [ 0x30 >> 1 ] = "IR (hauppauge)",
        [ 0x80 >> 1 ] = "msp34xx",
        [ 0x86 >> 1 ] = "tda9887",
index f7b5543a96a1bf760df9ff1c96f01fba8d4a7968..e8aada772b89b55d71411eb286648d306d6fdf41 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-if.c,v 1.4 2004/11/17 18:47:47 kraxel Exp $
 
     bttv-if.c  --  old gpio interface to other kernel modules
                    don't use in new code, will go away in 2.7
index 9ed21fd190c6cc24ed3e5fc5a57360956f77e8b6..a5ed99b8944519a676057cad38dc22ee1507d48b 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-risc.c,v 1.10 2004/11/19 18:07:12 kraxel Exp $
 
     bttv-risc.c  --  interfaces to other kernel modules
 
index 06f3e62b3e8d024fc336664e609ab040c36aad7d..f4f58c60f152b2d178156c211ef13aad1a493bd5 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttv-vbi.c,v 1.9 2005/01/13 17:22:33 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
     vbi interface
index f2af9e1454f08f8039b83587a6acd843975d9584..d254e90e3bb9fe8718a58bb8b080860b2f2b66e2 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: bttv.h,v 1.22 2005/07/28 18:41:21 mchehab Exp $
  *
  *  bttv - Bt848 frame grabber driver
  *
@@ -218,6 +217,8 @@ struct tvcard
 #define PLL_35   2
 
        unsigned int tuner_type;
+       unsigned int tuner_addr;
+
        unsigned int has_radio;
        void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set);
        void (*muxsel_hook)(struct bttv *btv, unsigned int input);
index aab094bc243dd17b383e1d11c7e8c6db19bbcf4a..9b0b7ca035f8a1f99d2be789bfb16255829b9d20 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: bttvp.h,v 1.21 2005/07/15 21:44:14 mchehab Exp $
 
     bttv - Bt848 frame grabber driver
 
index cdda423386c5ca3cdf33246893a0f80a82729908..9774e94d1e7d94ae7e8a8eb46a7e72b936680e8d 100644 (file)
@@ -445,10 +445,8 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
                ucpia->sbuf[1].urb = NULL;
        }
 
-       if (ucpia->sbuf[1].data) {
-               kfree(ucpia->sbuf[1].data);
-               ucpia->sbuf[1].data = NULL;
-       }
+       kfree(ucpia->sbuf[1].data);
+       ucpia->sbuf[1].data = NULL;
  
        if (ucpia->sbuf[0].urb) {
                usb_kill_urb(ucpia->sbuf[0].urb);
@@ -456,10 +454,8 @@ static void cpia_usb_free_resources(struct usb_cpia *ucpia, int try)
                ucpia->sbuf[0].urb = NULL;
        }
 
-       if (ucpia->sbuf[0].data) {
-               kfree(ucpia->sbuf[0].data);
-               ucpia->sbuf[0].data = NULL;
-       }
+       kfree(ucpia->sbuf[0].data);
+       ucpia->sbuf[0].data = NULL;
 }
 
 static int cpia_usb_close(void *privdata)
@@ -623,20 +619,14 @@ static void cpia_disconnect(struct usb_interface *intf)
 
        ucpia->curbuff = ucpia->workbuff = NULL;
 
-       if (ucpia->buffers[2]) {
-               vfree(ucpia->buffers[2]);
-               ucpia->buffers[2] = NULL;
-       }
+       vfree(ucpia->buffers[2]);
+       ucpia->buffers[2] = NULL;
 
-       if (ucpia->buffers[1]) {
-               vfree(ucpia->buffers[1]);
-               ucpia->buffers[1] = NULL;
-       }
+       vfree(ucpia->buffers[1]);
+       ucpia->buffers[1] = NULL;
 
-       if (ucpia->buffers[0]) {
-               vfree(ucpia->buffers[0]);
-               ucpia->buffers[0] = NULL;
-       }
+       vfree(ucpia->buffers[0]);
+       ucpia->buffers[0] = NULL;
 
        cam->lowlevel_data = NULL;
        kfree(ucpia);
index 4f39688f780a24a3d6b2677eae1dbe9b1477b366..0c0c59e94774911a0f27a086568b161b464058f3 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $
  *
  *  Support for a cx23416 mpeg encoder via cx2388x host port.
  *  "blackbird" reference design.
@@ -62,7 +61,6 @@ static LIST_HEAD(cx8802_devlist);
 #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
 
 /* Firmware API commands */
-/* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */
 #define IVTV_API_STD_TIMEOUT 500
 
 #define BLACKBIRD_API_PING               0x80
@@ -696,7 +694,6 @@ static void blackbird_codec_settings(struct cx8802_dev *dev)
 
        /* assign stream type */
        blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM);
-       /* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */
 
        /* assign output port */
        blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
@@ -824,7 +821,8 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
                        BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
-       blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */
+       /* initialize the video input */
+       blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0);
 
        msleep(1);
 
@@ -833,11 +831,12 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
        blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
        msleep(1);
 
-       /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */
+       /* start capturing to the host interface */
+       /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */
        blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
                        BLACKBIRD_MPEG_CAPTURE,
                        BLACKBIRD_RAW_BITS_NONE
-               ); /* start capturing to the host interface */
+               );
        msleep(10);
 
        blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
@@ -851,8 +850,8 @@ static int bb_buf_setup(struct videobuf_queue *q,
 {
        struct cx8802_fh *fh = q->priv_data;
 
-       fh->dev->ts_packet_size  = 512;
-       fh->dev->ts_packet_count = 100;
+       fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
+       fh->dev->ts_packet_count = 32; /* was: 100 */
 
        *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
        if (0 == *count)
@@ -900,12 +899,36 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
 {
        struct cx8802_fh  *fh  = file->private_data;
        struct cx8802_dev *dev = fh->dev;
+       struct cx88_core  *core = dev->core;
 
        if (debug > 1)
-               cx88_print_ioctl(dev->core->name,cmd);
+               cx88_print_ioctl(core->name,cmd);
 
        switch (cmd) {
 
+       /* --- capabilities ------------------------------------------ */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               memset(cap,0,sizeof(*cap));
+               strcpy(cap->driver, "cx88_blackbird");
+               strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card));
+               sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+               cap->version = CX88_VERSION_CODE;
+               cap->capabilities =
+                       V4L2_CAP_VIDEO_CAPTURE |
+                       V4L2_CAP_READWRITE     |
+                       V4L2_CAP_STREAMING     |
+                       V4L2_CAP_VBI_CAPTURE   |
+                       V4L2_CAP_VIDEO_OVERLAY |
+                       0;
+               if (UNSET != core->tuner_type)
+                       cap->capabilities |= V4L2_CAP_TUNER;
+
+               return 0;
+       }
+
        /* --- capture ioctls ---------------------------------------- */
        case VIDIOC_ENUM_FMT:
        {
@@ -935,7 +958,11 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
                f->fmt.pix.width        = dev->width;
                f->fmt.pix.height       = dev->height;
                f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-               f->fmt.pix.sizeimage    = 1024 * 512 /* FIXME: BUFFER_SIZE */;
+               f->fmt.pix.field        = V4L2_FIELD_NONE;
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage    = 188 * 4 * 1024; /* 1024 * 512 */ /* FIXME: BUFFER_SIZE */;
+               f->fmt.pix.colorspace   = 0;
+               return 0;
        }
 
        /* --- streaming capture ------------------------------------- */
@@ -959,15 +986,25 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
                return videobuf_streamoff(&fh->mpegq);
 
        default:
-               return -EINVAL;
+               return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
        }
        return 0;
 }
 
+int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+                       unsigned int cmd, void *arg);
+unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
+static unsigned int mpeg_translate_ioctl(unsigned int cmd)
+{
+       return cmd;
+}
+
 static int mpeg_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg)
+                       unsigned int cmd, unsigned long arg)
 {
-       return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
+       cmd = cx88_ioctl_translator( cmd );
+       return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
 }
 
 static int mpeg_open(struct inode *inode, struct file *file)
@@ -1135,7 +1172,7 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
        dev->pci = pci_dev;
        dev->core = core;
        dev->width = 720;
-       dev->height = 480;
+       dev->height = 576;
 
        err = cx8802_init_common(dev);
        if (0 != err)
@@ -1148,6 +1185,9 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
 
        list_add_tail(&dev->devlist,&cx8802_devlist);
        blackbird_register_video(dev);
+
+       /* initial device configuration: needed ? */
+
        return 0;
 
  fail_free:
@@ -1202,6 +1242,8 @@ static int blackbird_init(void)
        printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
               SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
 #endif
+       cx88_ioctl_hook = mpeg_do_ioctl;
+       cx88_ioctl_translator = mpeg_translate_ioctl;
        return pci_register_driver(&blackbird_pci_driver);
 }
 
@@ -1213,6 +1255,9 @@ static void blackbird_fini(void)
 module_init(blackbird_init);
 module_exit(blackbird_fini);
 
+EXPORT_SYMBOL(cx88_ioctl_hook);
+EXPORT_SYMBOL(cx88_ioctl_translator);
+
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
index ebf02a7f81e801eaa9497fd91689630ecb4c48f9..4da91d535a5b0828fa3901d9a68502edb25da6eb 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-cards.c,v 1.90 2005/07/28 02:47:42 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * card-specific stuff.
@@ -499,9 +498,6 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                         .type   = CX88_VMUX_DVB,
                         .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
                 }},
                .dvb            = 1,
        },
@@ -614,12 +610,12 @@ struct cx88_board cx88_boards[] = {
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
-                       .gpio0  = 0xed12,  // internal decoder
+                       .gpio0  = 0xed12,  /* internal decoder */
                        .gpio2  = 0x00ff,
                },{
                        .type   = CX88_VMUX_DEBUG,
                        .vmux   = 0,
-                       .gpio0  = 0xff01,  // mono from tuner chip
+                       .gpio0  = 0xff01,  /* mono from tuner chip */
                },{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
@@ -715,19 +711,18 @@ struct cx88_board cx88_boards[] = {
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
-               /*  See DViCO FusionHDTV 3 Gold-Q for GPIO documentation.  */
                .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
                         .vmux   = 0,
-                        .gpio0  = 0x0f0d,
+                        .gpio0  = 0x97ed,
                 },{
                         .type   = CX88_VMUX_COMPOSITE1,
                         .vmux   = 1,
-                        .gpio0  = 0x0f00,
+                        .gpio0  = 0x97e9,
                 },{
                         .type   = CX88_VMUX_SVIDEO,
                         .vmux   = 2,
-                        .gpio0  = 0x0f00,
+                        .gpio0  = 0x97e9,
                 }},
                .dvb            = 1,
         },
@@ -765,20 +760,21 @@ struct cx88_board cx88_boards[] = {
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
-               /*  See DViCO FusionHDTV 3 Gold-Q for GPIO documentation.  */
+               .tda9887_conf   = TDA9887_PRESENT,
                .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
                         .vmux   = 0,
-                        .gpio0  = 0x0f0d,
+                        .gpio0  = 0x87fd,
                 },{
                         .type   = CX88_VMUX_COMPOSITE1,
                         .vmux   = 1,
-                        .gpio0  = 0x0f00,
+                        .gpio0  = 0x87f9,
                 },{
                         .type   = CX88_VMUX_SVIDEO,
                         .vmux   = 2,
-                        .gpio0  = 0x0f00,
+                        .gpio0  = 0x87f9,
                 }},
+               .dvb            = 1,
        },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -949,7 +945,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
 {
        struct tveeprom tv;
 
-       tveeprom_hauppauge_analog(&tv, eeprom_data);
+       tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
        core->tuner_type = tv.tuner_type;
        core->has_radio  = tv.has_radio;
 }
index 5e868f5cd0c0bae1cc84c9dfd2872b59694ba914..dc5c5c1f3461125234d021ed4fdbd79ae72bc2af 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-core.c,v 1.33 2005/07/07 14:17:47 mchehab Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * driver core
@@ -876,7 +875,7 @@ static int set_tvaudio(struct cx88_core *core)
 
        cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
        cx88_set_tvaudio(core);
-       // cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO);
+       /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
 
        cx_write(MO_AUDD_LNGTH,    128); /* fifo size */
        cx_write(MO_AUDR_LNGTH,    128); /* fifo size */
@@ -1087,10 +1086,17 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
        core->pci_bus  = pci->bus->number;
        core->pci_slot = PCI_SLOT(pci->devfn);
        core->pci_irqmask = 0x00fc00;
+       init_MUTEX(&core->lock);
 
        core->nr = cx88_devcount++;
        sprintf(core->name,"cx88[%d]",core->nr);
        if (0 != get_ressources(core,pci)) {
+               printk(KERN_ERR "CORE %s No more PCI ressources for "
+                       "subsystem: %04x:%04x, board: %s\n",
+                       core->name,pci->subsystem_vendor,
+                       pci->subsystem_device,
+                       cx88_boards[core->board].name);
+
                cx88_devcount--;
                goto fail_free;
        }
@@ -1114,11 +1120,11 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
                core->board = CX88_BOARD_UNKNOWN;
                cx88_card_list(core,pci);
        }
-        printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-              core->name,pci->subsystem_vendor,
-              pci->subsystem_device,cx88_boards[core->board].name,
-              core->board, card[core->nr] == core->board ?
-              "insmod option" : "autodetected");
+       printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+               core->name,pci->subsystem_vendor,
+               pci->subsystem_device,cx88_boards[core->board].name,
+               core->board, card[core->nr] == core->board ?
+               "insmod option" : "autodetected");
 
        core->tuner_type = tuner[core->nr];
        core->radio_type = radio[core->nr];
@@ -1202,4 +1208,5 @@ EXPORT_SYMBOL(cx88_core_put);
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
index 78d223257a6888650238e1a660bdf8d27be321d6..c9106b1d79dff67c83cdc442cdc01d02b6616ec1 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-dvb.c,v 1.58 2005/08/07 09:24:08 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * MPEG Transport Stream (DVB) routines
@@ -29,7 +28,7 @@
 #include <linux/kthread.h>
 #include <linux/file.h>
 #include <linux/suspend.h>
-#include <linux/config.h>
+
 
 #include "cx88.h"
 #include "dvb-pll.h"
@@ -210,16 +209,26 @@ static struct or51132_config pchdtv_hd3000 = {
 static int lgdt330x_pll_set(struct dvb_frontend* fe,
                            struct dvb_frontend_parameters* params)
 {
+       /* FIXME make this routine use the tuner-simple code.
+        * It could probably be shared with a number of ATSC
+        * frontends. Many share the same tuner with analog TV. */
+
        struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx88_core *core = dev->core;
        u8 buf[4];
        struct i2c_msg msg =
                { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
        int err;
 
-       dvb_pll_configure(dev->core->pll_desc, buf, params->frequency, 0);
+       /* Put the analog decoder in standby to keep it quiet */
+       if (core->tda9887_conf) {
+               cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+       }
+
+       dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
        dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
                        __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-       if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+       if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
                printk(KERN_WARNING "cx88-dvb: %s error "
                           "(addr %02x <- %02x, err = %i)\n",
                           __FUNCTION__, buf[0], buf[1], err);
@@ -228,6 +237,13 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe,
                else
                        return -EREMOTEIO;
        }
+       if (core->tuner_type == TUNER_LG_TDVS_H062F) {
+               /* Set the Auxiliary Byte. */
+               buf[2] &= ~0x20;
+               buf[2] |= 0x18;
+               buf[3] = 0x50;
+               i2c_transfer(&core->i2c_adap, &msg, 1);
+       }
        return 0;
 }
 
@@ -261,6 +277,14 @@ static struct lgdt330x_config fusionhdtv_3_gold = {
        .pll_set          = lgdt330x_pll_set,
        .set_ts_params    = lgdt330x_set_ts_param,
 };
+
+static struct lgdt330x_config fusionhdtv_5_gold = {
+       .demod_address    = 0x0e,
+       .demod_chip       = LGDT3303,
+       .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+       .pll_set          = lgdt330x_pll_set,
+       .set_ts_params    = lgdt330x_set_ts_param,
+};
 #endif
 
 static int dvb_register(struct cx8802_dev *dev)
@@ -346,6 +370,22 @@ static int dvb_register(struct cx8802_dev *dev)
                                                    &dev->core->i2c_adap);
                }
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+               dev->ts_gen_cntrl = 0x08;
+               {
+               /* Do a hardware reset of chip before using it. */
+               struct cx88_core *core = dev->core;
+
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 1);
+               mdelay(200);
+               dev->core->pll_addr = 0x61;
+               dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
+               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
+                                                   &dev->core->i2c_adap);
+               }
+               break;
 #endif
        default:
                printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
@@ -362,11 +402,6 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
        }
 
-       /* Copy the board name into the DVB structure */
-       strlcpy(dev->dvb.frontend->ops->info.name,
-               cx88_boards[dev->core->board].name,
-               sizeof(dev->dvb.frontend->ops->info.name));
-
        /* register everything */
        return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
 }
index 7f598039e0257602bf8016c9e097b982e2c257e3..761cebd40dbda8d3be3a1a539c5adc35ae3cd0d2 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: cx88-i2c.c,v 1.30 2005/07/25 05:10:13 mkrufky Exp $
 
     cx88-i2c.c  --  all the i2c code is here
 
index 21488779819211555eb47b19bbec397ff662fca5..d81b21d6e05d0ded4fbee113170c801dc2f22f08 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-input.c,v 1.15 2005/07/07 13:58:38 mchehab Exp $
  *
  * Device driver for GPIO attached remote control interfaces
  * on Conexant 2388x based TV/DVB cards.
@@ -212,6 +211,53 @@ static IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = {
 
 /* ---------------------------------------------------------------------- */
 
+/* Cinergy 1400 DVB-T */
+static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
+       [0x01] = KEY_POWER,
+       [0x02] = KEY_1,
+       [0x03] = KEY_2,
+       [0x04] = KEY_3,
+       [0x05] = KEY_4,
+       [0x06] = KEY_5,
+       [0x07] = KEY_6,
+       [0x08] = KEY_7,
+       [0x09] = KEY_8,
+       [0x0a] = KEY_9,
+       [0x0c] = KEY_0,
+
+       [0x0b] = KEY_VIDEO,
+       [0x0d] = KEY_REFRESH,
+       [0x0e] = KEY_SELECT,
+       [0x0f] = KEY_EPG,
+       [0x10] = KEY_UP,
+       [0x11] = KEY_LEFT,
+       [0x12] = KEY_OK,
+       [0x13] = KEY_RIGHT,
+       [0x14] = KEY_DOWN,
+       [0x15] = KEY_TEXT,
+       [0x16] = KEY_INFO,
+
+       [0x17] = KEY_RED,
+       [0x18] = KEY_GREEN,
+       [0x19] = KEY_YELLOW,
+       [0x1a] = KEY_BLUE,
+
+       [0x1b] = KEY_CHANNELUP,
+       [0x1c] = KEY_VOLUMEUP,
+       [0x1d] = KEY_MUTE,
+       [0x1e] = KEY_VOLUMEDOWN,
+       [0x1f] = KEY_CHANNELDOWN,
+
+       [0x40] = KEY_PAUSE,
+       [0x4c] = KEY_PLAY,
+       [0x58] = KEY_RECORD,
+       [0x54] = KEY_PREVIOUS,
+       [0x48] = KEY_STOP,
+       [0x5c] = KEY_NEXT,
+};
+
+/* ---------------------------------------------------------------------- */
+
 struct cx88_IR {
        struct cx88_core *core;
        struct input_dev input;
@@ -241,7 +287,7 @@ module_param(ir_debug, int, 0644);  /* debug level [IR] */
 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 
 #define ir_dprintk(fmt, arg...)        if (ir_debug) \
-       printk(KERN_DEBUG "%s IR: " fmt , ir->core->name, ## arg)
+       printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
 
 /* ---------------------------------------------------------------------- */
 
@@ -329,6 +375,11 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir->mask_keyup = 0x60;
                ir->polling = 50; /* ms */
                break;
+       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+               ir_codes = ir_codes_cinergy_1400;
+               ir_type = IR_TYPE_PD;
+               ir->sampling = 1;
+               break;
        case CX88_BOARD_HAUPPAUGE:
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
                ir_codes = ir_codes_hauppauge_new;
@@ -394,6 +445,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir->input.id.vendor = pci->vendor;
                ir->input.id.product = pci->device;
        }
+       ir->input.dev = &pci->dev;
 
        /* record handles to ourself */
        ir->core = core;
@@ -445,7 +497,7 @@ int cx88_ir_fini(struct cx88_core *core)
 void cx88_ir_irq(struct cx88_core *core)
 {
        struct cx88_IR *ir = core->ir;
-       u32 samples, rc5;
+       u32 samples, ircode;
        int i;
 
        if (NULL == ir)
@@ -477,13 +529,44 @@ void cx88_ir_irq(struct cx88_core *core)
 
        /* decode it */
        switch (core->board) {
+       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+               ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
+
+               if (ircode == 0xffffffff) { /* decoding error */
+                       ir_dprintk("pulse distance decoding error\n");
+                       break;
+               }
+
+               ir_dprintk("pulse distance decoded: %x\n", ircode);
+
+               if (ircode == 0) { /* key still pressed */
+                       ir_dprintk("pulse distance decoded repeat code\n");
+                       ir->release = jiffies + msecs_to_jiffies(120);
+                       break;
+               }
+
+               if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
+                       ir_dprintk("pulse distance decoded wrong address\n");
+                       break;
+               }
+
+               if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */
+                       ir_dprintk("pulse distance decoded wrong check sum\n");
+                       break;
+               }
+
+               ir_dprintk("Key Code: %x\n", (ircode >> 16) & 0x7f);
+
+               ir_input_keydown(&ir->input, &ir->ir, (ircode >> 16) & 0x7f, (ircode >> 16) & 0xff);
+               ir->release = jiffies + msecs_to_jiffies(120);
+               break;
        case CX88_BOARD_HAUPPAUGE:
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
-               rc5 = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
-               ir_dprintk("biphase decoded: %x\n", rc5);
-               if ((rc5 & 0xfffff000) != 0x3000)
+               ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
+               ir_dprintk("biphase decoded: %x\n", ircode);
+               if ((ircode & 0xfffff000) != 0x3000)
                        break;
-               ir_input_keydown(&ir->input, &ir->ir, rc5 & 0x3f, rc5);
+               ir_input_keydown(&ir->input, &ir->ir, ircode & 0x3f, ircode);
                ir->release = jiffies + msecs_to_jiffies(120);
                break;
        }
index fe2767c0ff944abccf951b2f1fe435896f9a078b..ee2300e1ae0b7024830fc2bc7a752d8d89e36682 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-mpeg.c,v 1.31 2005/07/07 14:17:47 mchehab Exp $
  *
  *  Support for the mpeg transport stream transfers
  *  PCI function #2 of the cx2388x.
@@ -73,11 +72,15 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                udelay(100);
                cx_write(MO_PINMUX_IO, 0x00);
                cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01);
-               if ((core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q) ||
-                   (core->board == CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T)) {
+               switch (core->board) {
+               case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+               case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+               case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
                        cx_write(TS_SOP_STAT, 1<<13);
-               } else {
+                       break;
+               default:
                        cx_write(TS_SOP_STAT, 0x00);
+                       break;
                }
                cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
                udelay(100);
@@ -86,12 +89,10 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
        if (cx88_boards[core->board].blackbird) {
                cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
 
-               // cx_write(TS_F2_CMD_STAT_MM, 0x2900106); /* F2_CMD_STAT_MM defaults + master + memory space */
                cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
                udelay(100);
 
                cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
-               //cx_write(TS_HW_SOP_CNTRL, 0x2F0BC0); /* mpeg start byte ts: 0x2F0BC0 ? */
                cx_write(TS_VALERR_CNTRL, 0x2000);
 
                cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
@@ -106,7 +107,6 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
        dprintk( 0, "setting the interrupt mask\n" );
        cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
        cx_set(MO_TS_INTMSK,  0x1f0011);
-       //cx_write(MO_TS_INTMSK,  0x0f0011);
 
        /* start dma */
        cx_set(MO_DEV_CNTRL2, (1<<5));
@@ -206,7 +206,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
                mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
                dprintk(0,"[%p/%d] %s - first active\n",
                        buf, buf->vb.i, __FUNCTION__);
-               //udelay(100);
 
        } else {
                dprintk( 1, "queue is not empty - append to active\n" );
@@ -217,7 +216,6 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
                prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
                dprintk( 1, "[%p/%d] %s - append to active\n",
                        buf, buf->vb.i, __FUNCTION__);
-               //udelay(100);
        }
 }
 
@@ -387,7 +385,6 @@ int cx8802_init_common(struct cx8802_dev *dev)
               dev->pci_lat,pci_resource_start(dev->pci,0));
 
        /* initialize driver struct */
-        init_MUTEX(&dev->lock);
        spin_lock_init(&dev->slock);
 
        /* init dma queue */
@@ -458,14 +455,28 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
 
 int cx8802_resume_common(struct pci_dev *pci_dev)
 {
-        struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
        struct cx88_core *core = dev->core;
+       int err;
 
        if (dev->state.disabled) {
-               pci_enable_device(pci_dev);
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       printk(KERN_ERR "%s: can't enable device\n",
+                                              dev->core->name);
+                       return err;
+               }
                dev->state.disabled = 0;
        }
-       pci_set_power_state(pci_dev, PCI_D0);
+       err=pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               printk(KERN_ERR "%s: can't enable device\n",
+                                              dev->core->name);
+               pci_disable_device(pci_dev);
+               dev->state.disabled = 1;
+
+               return err;
+       }
        pci_restore_state(pci_dev);
 
        /* FIXME: re-initialize hardware */
index 37f82662d26517ada3e02fd1c098eafba8fc30d0..0a3a62fc9bbb729dafa5a33e781963c88f9fd099 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: cx88-reg.h,v 1.8 2005/07/07 13:58:38 mchehab Exp $
 
     cx88x-hw.h - CX2388x register offsets
 
 #define CX88X_EN_TBFX 0x02
 #define CX88X_EN_VSFX 0x04
 
+/* ---------------------------------------------------------------------- */
+/* PCI controller registers                                               */
+
+/* Command and Status Register */
+#define F0_CMD_STAT_MM      0x2f0004
+#define F1_CMD_STAT_MM      0x2f0104
+#define F2_CMD_STAT_MM      0x2f0204
+#define F3_CMD_STAT_MM      0x2f0304
+#define F4_CMD_STAT_MM      0x2f0404
+
+/* Device Control #1 */
+#define F0_DEV_CNTRL1_MM    0x2f0040
+#define F1_DEV_CNTRL1_MM    0x2f0140
+#define F2_DEV_CNTRL1_MM    0x2f0240
+#define F3_DEV_CNTRL1_MM    0x2f0340
+#define F4_DEV_CNTRL1_MM    0x2f0440
+
+/* Device Control #1 */
+#define F0_BAR0_MM          0x2f0010
+#define F1_BAR0_MM          0x2f0110
+#define F2_BAR0_MM          0x2f0210
+#define F3_BAR0_MM          0x2f0310
+#define F4_BAR0_MM          0x2f0410
 
 /* ---------------------------------------------------------------------- */
 /* DMA Controller registers                                               */
index 91207f10bae778eb354cd5ae666cb2c7377bc8cb..2765acee0285f7fe216a2d0718731abde310aa59 100644 (file)
@@ -1,5 +1,4 @@
 /*
-    $Id: cx88-tvaudio.c,v 1.37 2005/07/07 13:58:38 mchehab Exp $
 
     cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
 
@@ -121,25 +120,19 @@ static void set_audio_registers(struct cx88_core *core,
 }
 
 static void set_audio_start(struct cx88_core *core,
-                           u32 mode, u32 ctl)
+                       u32 mode)
 {
        // mute
        cx_write(AUD_VOL_CTL,       (1 << 6));
 
-       //  increase level of input by 12dB
-//     cx_write(AUD_AFE_12DB_EN,   0x0001);
-       cx_write(AUD_AFE_12DB_EN,   0x0000);
-
        // start programming
        cx_write(AUD_CTL,           0x0000);
        cx_write(AUD_INIT,          mode);
        cx_write(AUD_INIT_LD,       0x0001);
        cx_write(AUD_SOFT_RESET,    0x0001);
-
-       cx_write(AUD_CTL,           ctl);
 }
 
-static void set_audio_finish(struct cx88_core *core)
+static void set_audio_finish(struct cx88_core *core, u32 ctl)
 {
        u32 volume;
 
@@ -154,25 +147,25 @@ static void set_audio_finish(struct cx88_core *core)
                cx_write(AUD_I2SOUTPUTCNTL, 1);
                cx_write(AUD_I2SCNTL, 0);
                //cx_write(AUD_APB_IN_RATE_ADJ, 0);
+       } else {
+       ctl |= EN_DAC_ENABLE;
+       cx_write(AUD_CTL, ctl);
        }
 
-       // finish programming
+       /* finish programming */
        cx_write(AUD_SOFT_RESET, 0x0000);
 
-       // start audio processing
-       cx_set(AUD_CTL, EN_DAC_ENABLE);
-
-       // unmute
+       /* unmute */
        volume = cx_sread(SHADOW_AUD_VOL_CTL);
        cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
 }
 
 /* ----------------------------------------------------------- */
 
-static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
+static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, u32 mode)
 {
        static const struct rlist btsc[] = {
-               /* from dscaler */
+       { AUD_AFE_12DB_EN,             0x00000001 },
                { AUD_OUT1_SEL,                0x00000013 },
                { AUD_OUT1_SHIFT,              0x00000000 },
                { AUD_POLY0_DDS_CONSTANT,      0x0012010c },
@@ -206,9 +199,10 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
                { AUD_RDSI_SHIFT,              0x00000000 },
                { AUD_RDSQ_SHIFT,              0x00000000 },
                { AUD_POLYPH80SCALEFAC,        0x00000003 },
-                { /* end of list */ },
+               { /* end of list */ },
        };
        static const struct rlist btsc_sap[] = {
+       { AUD_AFE_12DB_EN,             0x00000001 },
                { AUD_DBX_IN_GAIN,             0x00007200 },
                { AUD_DBX_WBE_GAIN,            0x00006200 },
                { AUD_DBX_SE_GAIN,             0x00006200 },
@@ -259,371 +253,400 @@ static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap)
                { AUD_RDSI_SHIFT,              0x00000000 },
                { AUD_RDSQ_SHIFT,              0x00000000 },
                { AUD_POLYPH80SCALEFAC,        0x00000003 },
-                { /* end of list */ },
+               { /* end of list */ },
        };
 
-       // dscaler: exactly taken from driver,
-       // dscaler: don't know why to set EN_FMRADIO_EN_RDS
+       mode |= EN_FMRADIO_EN_RDS;
+
        if (sap) {
                dprintk("%s SAP (status: unknown)\n",__FUNCTION__);
-               set_audio_start(core, 0x0001,
-                               EN_FMRADIO_EN_RDS | EN_BTSC_FORCE_SAP);
+       set_audio_start(core, SEL_SAP);
                set_audio_registers(core, btsc_sap);
+               set_audio_finish(core, mode);
        } else {
                dprintk("%s (status: known-good)\n",__FUNCTION__);
-               set_audio_start(core, 0x0001,
-                               EN_FMRADIO_EN_RDS | EN_BTSC_AUTO_STEREO);
+       set_audio_start(core, SEL_BTSC);
                set_audio_registers(core, btsc);
+               set_audio_finish(core, mode);
        }
-       set_audio_finish(core);
 }
 
 
 static void set_audio_standard_NICAM_L(struct cx88_core *core, int stereo)
 {
-        /* This is probably weird..
-         * Let's operate and find out. */
-
-        static const struct rlist nicam_l_mono[] = {
-                { AUD_ERRLOGPERIOD_R,     0x00000064 },
-                { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
-                { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
-                { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
-
-                { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
-                { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
-                { AUD_QAM_MODE,           0x00 },
-                { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
-                { AUD_PHACC_FREQ_8MSB,    0x3a },
-                { AUD_PHACC_FREQ_8LSB,    0x4a },
-
-                { AUD_DEEMPHGAIN_R, 0x6680 },
-                { AUD_DEEMPHNUMER1_R, 0x353DE },
-                { AUD_DEEMPHNUMER2_R, 0x1B1 },
-                { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
-                { AUD_DEEMPHDENOM2_R, 0x0 },
-                { AUD_FM_MODE_ENABLE, 0x7 },
-                { AUD_POLYPH80SCALEFAC, 0x3 },
-                { AUD_AFE_12DB_EN, 0x1 },
-                { AAGC_GAIN, 0x0 },
-                { AAGC_HYST, 0x18 },
-                { AAGC_DEF, 0x20 },
-                { AUD_DN0_FREQ, 0x0 },
-                { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
-                { AUD_DCOC_0_SRC, 0x21 },
-                { AUD_IIR1_0_SEL, 0x0 },
-                { AUD_IIR1_0_SHIFT, 0x7 },
-                { AUD_IIR1_1_SEL, 0x2 },
-                { AUD_IIR1_1_SHIFT, 0x0 },
-                { AUD_DCOC_1_SRC, 0x3 },
-                { AUD_DCOC1_SHIFT, 0x0 },
-                { AUD_DCOC_PASS_IN, 0x0 },
-                { AUD_IIR1_2_SEL, 0x23 },
-                { AUD_IIR1_2_SHIFT, 0x0 },
-                { AUD_IIR1_3_SEL, 0x4 },
-                { AUD_IIR1_3_SHIFT, 0x7 },
-                { AUD_IIR1_4_SEL, 0x5 },
-                { AUD_IIR1_4_SHIFT, 0x7 },
-                { AUD_IIR3_0_SEL, 0x7 },
-                { AUD_IIR3_0_SHIFT, 0x0 },
-                { AUD_DEEMPH0_SRC_SEL, 0x11 },
-                { AUD_DEEMPH0_SHIFT, 0x0 },
-                { AUD_DEEMPH0_G0, 0x7000 },
-                { AUD_DEEMPH0_A0, 0x0 },
-                { AUD_DEEMPH0_B0, 0x0 },
-                { AUD_DEEMPH0_A1, 0x0 },
-                { AUD_DEEMPH0_B1, 0x0 },
-                { AUD_DEEMPH1_SRC_SEL, 0x11 },
-                { AUD_DEEMPH1_SHIFT, 0x0 },
-                { AUD_DEEMPH1_G0, 0x7000 },
-                { AUD_DEEMPH1_A0, 0x0 },
-                { AUD_DEEMPH1_B0, 0x0 },
-                { AUD_DEEMPH1_A1, 0x0 },
-                { AUD_DEEMPH1_B1, 0x0 },
-                { AUD_OUT0_SEL, 0x3F },
-                { AUD_OUT1_SEL, 0x3F },
-                { AUD_DMD_RA_DDS, 0x0F5C285 },
-                { AUD_PLL_INT, 0x1E },
-                { AUD_PLL_DDS, 0x0 },
-                { AUD_PLL_FRAC, 0x0E542 },
-
-                // setup QAM registers
-                { AUD_RATE_ADJ1,      0x00000100 },
-                { AUD_RATE_ADJ2,      0x00000200 },
-                { AUD_RATE_ADJ3,      0x00000300 },
-                { AUD_RATE_ADJ4,      0x00000400 },
-                { AUD_RATE_ADJ5,      0x00000500 },
-                { AUD_RATE_THRES_DMD, 0x000000C0 },
-                { /* end of list */ },
-        };
-
-        static const struct rlist nicam_l[] = {
-                // setup QAM registers
-                { AUD_RATE_ADJ1, 0x00000060 },
-                { AUD_RATE_ADJ2, 0x000000F9 },
-                { AUD_RATE_ADJ3, 0x000001CC },
-                { AUD_RATE_ADJ4, 0x000002B3 },
-                { AUD_RATE_ADJ5, 0x00000726 },
-                { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
-                { AUD_DEEMPHDENOM2_R, 0x00000000 },
-                { AUD_ERRLOGPERIOD_R, 0x00000064 },
-                { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
-                { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
-                { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
-                { AUD_POLYPH80SCALEFAC, 0x00000003 },
-                { AUD_DMD_RA_DDS, 0x00C00000 },
-                { AUD_PLL_INT, 0x0000001E },
-                { AUD_PLL_DDS, 0x00000000 },
-                { AUD_PLL_FRAC, 0x0000E542 },
-                { AUD_START_TIMER, 0x00000000 },
-                { AUD_DEEMPHNUMER1_R, 0x000353DE },
-                { AUD_DEEMPHNUMER2_R, 0x000001B1 },
-                { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
-                { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
-                { AUD_QAM_MODE, 0x05 },
-                { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
-                { AUD_PHACC_FREQ_8MSB, 0x34 },
-                { AUD_PHACC_FREQ_8LSB, 0x4C },
-                { AUD_DEEMPHGAIN_R, 0x00006680 },
-                { AUD_RATE_THRES_DMD, 0x000000C0  },
-                { /* end of list */ },
-        } ;
-        dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
-
-        if (!stereo) {
-               /* AM mono sound */
-                set_audio_start(core, 0x0004,
-                               0x100c /* FIXME again */);
-                set_audio_registers(core, nicam_l_mono);
-        } else {
-                set_audio_start(core, 0x0010,
-                               0x1924 /* FIXME again */);
-                set_audio_registers(core, nicam_l);
-        }
-        set_audio_finish(core);
+       /* This is probably weird..
+       * Let's operate and find out. */
+
+       static const struct rlist nicam_l_mono[] = {
+               { AUD_ERRLOGPERIOD_R,     0x00000064 },
+               { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+               { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+               { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+
+               { AUD_PDF_DDS_CNST_BYTE2, 0x48 },
+               { AUD_PDF_DDS_CNST_BYTE1, 0x3D },
+               { AUD_QAM_MODE,           0x00 },
+               { AUD_PDF_DDS_CNST_BYTE0, 0xf5 },
+               { AUD_PHACC_FREQ_8MSB,    0x3a },
+               { AUD_PHACC_FREQ_8LSB,    0x4a },
+
+               { AUD_DEEMPHGAIN_R, 0x6680 },
+               { AUD_DEEMPHNUMER1_R, 0x353DE },
+               { AUD_DEEMPHNUMER2_R, 0x1B1 },
+               { AUD_DEEMPHDENOM1_R, 0x0F3D0 },
+               { AUD_DEEMPHDENOM2_R, 0x0 },
+               { AUD_FM_MODE_ENABLE, 0x7 },
+               { AUD_POLYPH80SCALEFAC, 0x3 },
+               { AUD_AFE_12DB_EN, 0x1 },
+               { AAGC_GAIN, 0x0 },
+               { AAGC_HYST, 0x18 },
+               { AAGC_DEF, 0x20 },
+               { AUD_DN0_FREQ, 0x0 },
+               { AUD_POLY0_DDS_CONSTANT, 0x0E4DB2 },
+               { AUD_DCOC_0_SRC, 0x21 },
+               { AUD_IIR1_0_SEL, 0x0 },
+               { AUD_IIR1_0_SHIFT, 0x7 },
+               { AUD_IIR1_1_SEL, 0x2 },
+               { AUD_IIR1_1_SHIFT, 0x0 },
+               { AUD_DCOC_1_SRC, 0x3 },
+               { AUD_DCOC1_SHIFT, 0x0 },
+               { AUD_DCOC_PASS_IN, 0x0 },
+               { AUD_IIR1_2_SEL, 0x23 },
+               { AUD_IIR1_2_SHIFT, 0x0 },
+               { AUD_IIR1_3_SEL, 0x4 },
+               { AUD_IIR1_3_SHIFT, 0x7 },
+               { AUD_IIR1_4_SEL, 0x5 },
+               { AUD_IIR1_4_SHIFT, 0x7 },
+               { AUD_IIR3_0_SEL, 0x7 },
+               { AUD_IIR3_0_SHIFT, 0x0 },
+               { AUD_DEEMPH0_SRC_SEL, 0x11 },
+               { AUD_DEEMPH0_SHIFT, 0x0 },
+               { AUD_DEEMPH0_G0, 0x7000 },
+               { AUD_DEEMPH0_A0, 0x0 },
+               { AUD_DEEMPH0_B0, 0x0 },
+               { AUD_DEEMPH0_A1, 0x0 },
+               { AUD_DEEMPH0_B1, 0x0 },
+               { AUD_DEEMPH1_SRC_SEL, 0x11 },
+               { AUD_DEEMPH1_SHIFT, 0x0 },
+               { AUD_DEEMPH1_G0, 0x7000 },
+               { AUD_DEEMPH1_A0, 0x0 },
+               { AUD_DEEMPH1_B0, 0x0 },
+               { AUD_DEEMPH1_A1, 0x0 },
+               { AUD_DEEMPH1_B1, 0x0 },
+               { AUD_OUT0_SEL, 0x3F },
+               { AUD_OUT1_SEL, 0x3F },
+               { AUD_DMD_RA_DDS, 0x0F5C285 },
+               { AUD_PLL_INT, 0x1E },
+               { AUD_PLL_DDS, 0x0 },
+               { AUD_PLL_FRAC, 0x0E542 },
+
+               // setup QAM registers
+               { AUD_RATE_ADJ1,      0x00000100 },
+               { AUD_RATE_ADJ2,      0x00000200 },
+               { AUD_RATE_ADJ3,      0x00000300 },
+               { AUD_RATE_ADJ4,      0x00000400 },
+               { AUD_RATE_ADJ5,      0x00000500 },
+               { AUD_RATE_THRES_DMD, 0x000000C0 },
+               { /* end of list */ },
+       };
 
+       static const struct rlist nicam_l[] = {
+               // setup QAM registers
+               { AUD_RATE_ADJ1, 0x00000060 },
+               { AUD_RATE_ADJ2, 0x000000F9 },
+               { AUD_RATE_ADJ3, 0x000001CC },
+               { AUD_RATE_ADJ4, 0x000002B3 },
+               { AUD_RATE_ADJ5, 0x00000726 },
+               { AUD_DEEMPHDENOM1_R, 0x0000F3D0 },
+               { AUD_DEEMPHDENOM2_R, 0x00000000 },
+               { AUD_ERRLOGPERIOD_R, 0x00000064 },
+               { AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF },
+               { AUD_ERRINTRPTTHSHLD2_R, 0x0000001F },
+               { AUD_ERRINTRPTTHSHLD3_R, 0x0000000F },
+               { AUD_POLYPH80SCALEFAC, 0x00000003 },
+               { AUD_DMD_RA_DDS, 0x00C00000 },
+               { AUD_PLL_INT, 0x0000001E },
+               { AUD_PLL_DDS, 0x00000000 },
+               { AUD_PLL_FRAC, 0x0000E542 },
+               { AUD_START_TIMER, 0x00000000 },
+               { AUD_DEEMPHNUMER1_R, 0x000353DE },
+               { AUD_DEEMPHNUMER2_R, 0x000001B1 },
+               { AUD_PDF_DDS_CNST_BYTE2, 0x06 },
+               { AUD_PDF_DDS_CNST_BYTE1, 0x82 },
+               { AUD_QAM_MODE, 0x05 },
+               { AUD_PDF_DDS_CNST_BYTE0, 0x12 },
+               { AUD_PHACC_FREQ_8MSB, 0x34 },
+               { AUD_PHACC_FREQ_8LSB, 0x4C },
+               { AUD_DEEMPHGAIN_R, 0x00006680 },
+               { AUD_RATE_THRES_DMD, 0x000000C0  },
+               { /* end of list */ },
+       } ;
+       dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+       if (!stereo) {
+       /* AM Mono */
+               set_audio_start(core, SEL_A2);
+               set_audio_registers(core, nicam_l_mono);
+       set_audio_finish(core, EN_A2_FORCE_MONO1);
+       } else {
+       /* Nicam Stereo */
+               set_audio_start(core, SEL_NICAM);
+               set_audio_registers(core, nicam_l);
+       set_audio_finish(core, 0x1924); /* FIXME */
+       }
 }
 
 static void set_audio_standard_PAL_I(struct cx88_core *core, int stereo)
 {
        static const struct rlist pal_i_fm_mono[] = {
-            {AUD_ERRLOGPERIOD_R,       0x00000064},
-            {AUD_ERRINTRPTTHSHLD1_R,   0x00000fff},
-            {AUD_ERRINTRPTTHSHLD2_R,   0x0000001f},
-            {AUD_ERRINTRPTTHSHLD3_R,   0x0000000f},
-            {AUD_PDF_DDS_CNST_BYTE2,   0x06},
-            {AUD_PDF_DDS_CNST_BYTE1,   0x82},
-            {AUD_PDF_DDS_CNST_BYTE0,   0x12},
-            {AUD_QAM_MODE,             0x05},
-            {AUD_PHACC_FREQ_8MSB,      0x3a},
-            {AUD_PHACC_FREQ_8LSB,      0x93},
-            {AUD_DMD_RA_DDS,           0x002a4f2f},
-            {AUD_PLL_INT,              0x0000001e},
-            {AUD_PLL_DDS,              0x00000004},
-            {AUD_PLL_FRAC,             0x0000e542},
-            {AUD_RATE_ADJ1,            0x00000100},
-            {AUD_RATE_ADJ2,            0x00000200},
-            {AUD_RATE_ADJ3,            0x00000300},
-            {AUD_RATE_ADJ4,            0x00000400},
-            {AUD_RATE_ADJ5,            0x00000500},
-            {AUD_THR_FR,               0x00000000},
-            {AUD_PILOT_BQD_1_K0,       0x0000755b},
-            {AUD_PILOT_BQD_1_K1,       0x00551340},
-            {AUD_PILOT_BQD_1_K2,       0x006d30be},
-            {AUD_PILOT_BQD_1_K3,       0xffd394af},
-            {AUD_PILOT_BQD_1_K4,       0x00400000},
-            {AUD_PILOT_BQD_2_K0,       0x00040000},
-            {AUD_PILOT_BQD_2_K1,       0x002a4841},
-            {AUD_PILOT_BQD_2_K2,       0x00400000},
-            {AUD_PILOT_BQD_2_K3,       0x00000000},
-            {AUD_PILOT_BQD_2_K4,       0x00000000},
-            {AUD_MODE_CHG_TIMER,       0x00000060},
-            {AUD_AFE_12DB_EN,          0x00000001},
-            {AAGC_HYST,                0x0000000a},
-            {AUD_CORDIC_SHIFT_0,       0x00000007},
-            {AUD_CORDIC_SHIFT_1,       0x00000007},
-            {AUD_C1_UP_THR,            0x00007000},
-            {AUD_C1_LO_THR,            0x00005400},
-            {AUD_C2_UP_THR,            0x00005400},
-            {AUD_C2_LO_THR,            0x00003000},
-            {AUD_DCOC_0_SRC,           0x0000001a},
-            {AUD_DCOC0_SHIFT,          0x00000000},
-            {AUD_DCOC_0_SHIFT_IN0,     0x0000000a},
-            {AUD_DCOC_0_SHIFT_IN1,     0x00000008},
-            {AUD_DCOC_PASS_IN,         0x00000003},
-            {AUD_IIR3_0_SEL,           0x00000021},
-            {AUD_DN2_AFC,              0x00000002},
-            {AUD_DCOC_1_SRC,           0x0000001b},
-            {AUD_DCOC1_SHIFT,          0x00000000},
-            {AUD_DCOC_1_SHIFT_IN0,     0x0000000a},
-            {AUD_DCOC_1_SHIFT_IN1,     0x00000008},
-            {AUD_IIR3_1_SEL,           0x00000023},
-            {AUD_DN0_FREQ,             0x000035a3},
-            {AUD_DN2_FREQ,             0x000029c7},
-            {AUD_CRDC0_SRC_SEL,        0x00000511},
-            {AUD_IIR1_0_SEL,           0x00000001},
-            {AUD_IIR1_1_SEL,           0x00000000},
-            {AUD_IIR3_2_SEL,           0x00000003},
-            {AUD_IIR3_2_SHIFT,         0x00000000},
-            {AUD_IIR3_0_SEL,           0x00000002},
-            {AUD_IIR2_0_SEL,           0x00000021},
-            {AUD_IIR2_0_SHIFT,         0x00000002},
-            {AUD_DEEMPH0_SRC_SEL,      0x0000000b},
-            {AUD_DEEMPH1_SRC_SEL,      0x0000000b},
-            {AUD_POLYPH80SCALEFAC,     0x00000001},
-            {AUD_START_TIMER,          0x00000000},
-            { /* end of list */ },
+       {AUD_ERRLOGPERIOD_R,       0x00000064},
+       {AUD_ERRINTRPTTHSHLD1_R,   0x00000fff},
+       {AUD_ERRINTRPTTHSHLD2_R,   0x0000001f},
+       {AUD_ERRINTRPTTHSHLD3_R,   0x0000000f},
+       {AUD_PDF_DDS_CNST_BYTE2,   0x06},
+       {AUD_PDF_DDS_CNST_BYTE1,   0x82},
+       {AUD_PDF_DDS_CNST_BYTE0,   0x12},
+       {AUD_QAM_MODE,             0x05},
+       {AUD_PHACC_FREQ_8MSB,      0x3a},
+       {AUD_PHACC_FREQ_8LSB,      0x93},
+       {AUD_DMD_RA_DDS,           0x002a4f2f},
+       {AUD_PLL_INT,              0x0000001e},
+       {AUD_PLL_DDS,              0x00000004},
+       {AUD_PLL_FRAC,             0x0000e542},
+       {AUD_RATE_ADJ1,            0x00000100},
+       {AUD_RATE_ADJ2,            0x00000200},
+       {AUD_RATE_ADJ3,            0x00000300},
+       {AUD_RATE_ADJ4,            0x00000400},
+       {AUD_RATE_ADJ5,            0x00000500},
+       {AUD_THR_FR,               0x00000000},
+       {AUD_PILOT_BQD_1_K0,       0x0000755b},
+       {AUD_PILOT_BQD_1_K1,       0x00551340},
+       {AUD_PILOT_BQD_1_K2,       0x006d30be},
+       {AUD_PILOT_BQD_1_K3,       0xffd394af},
+       {AUD_PILOT_BQD_1_K4,       0x00400000},
+       {AUD_PILOT_BQD_2_K0,       0x00040000},
+       {AUD_PILOT_BQD_2_K1,       0x002a4841},
+       {AUD_PILOT_BQD_2_K2,       0x00400000},
+       {AUD_PILOT_BQD_2_K3,       0x00000000},
+       {AUD_PILOT_BQD_2_K4,       0x00000000},
+       {AUD_MODE_CHG_TIMER,       0x00000060},
+       {AUD_AFE_12DB_EN,          0x00000001},
+       {AAGC_HYST,                0x0000000a},
+       {AUD_CORDIC_SHIFT_0,       0x00000007},
+       {AUD_CORDIC_SHIFT_1,       0x00000007},
+       {AUD_C1_UP_THR,            0x00007000},
+       {AUD_C1_LO_THR,            0x00005400},
+       {AUD_C2_UP_THR,            0x00005400},
+       {AUD_C2_LO_THR,            0x00003000},
+       {AUD_DCOC_0_SRC,           0x0000001a},
+       {AUD_DCOC0_SHIFT,          0x00000000},
+       {AUD_DCOC_0_SHIFT_IN0,     0x0000000a},
+       {AUD_DCOC_0_SHIFT_IN1,     0x00000008},
+       {AUD_DCOC_PASS_IN,         0x00000003},
+       {AUD_IIR3_0_SEL,           0x00000021},
+       {AUD_DN2_AFC,              0x00000002},
+       {AUD_DCOC_1_SRC,           0x0000001b},
+       {AUD_DCOC1_SHIFT,          0x00000000},
+       {AUD_DCOC_1_SHIFT_IN0,     0x0000000a},
+       {AUD_DCOC_1_SHIFT_IN1,     0x00000008},
+       {AUD_IIR3_1_SEL,           0x00000023},
+       {AUD_DN0_FREQ,             0x000035a3},
+       {AUD_DN2_FREQ,             0x000029c7},
+       {AUD_CRDC0_SRC_SEL,        0x00000511},
+       {AUD_IIR1_0_SEL,           0x00000001},
+       {AUD_IIR1_1_SEL,           0x00000000},
+       {AUD_IIR3_2_SEL,           0x00000003},
+       {AUD_IIR3_2_SHIFT,         0x00000000},
+       {AUD_IIR3_0_SEL,           0x00000002},
+       {AUD_IIR2_0_SEL,           0x00000021},
+       {AUD_IIR2_0_SHIFT,         0x00000002},
+       {AUD_DEEMPH0_SRC_SEL,      0x0000000b},
+       {AUD_DEEMPH1_SRC_SEL,      0x0000000b},
+       {AUD_POLYPH80SCALEFAC,     0x00000001},
+       {AUD_START_TIMER,          0x00000000},
+       { /* end of list */ },
        };
 
        static const struct rlist pal_i_nicam[] = {
-           { AUD_RATE_ADJ1,           0x00000010 },
-           { AUD_RATE_ADJ2,           0x00000040 },
-           { AUD_RATE_ADJ3,           0x00000100 },
-           { AUD_RATE_ADJ4,           0x00000400 },
-           { AUD_RATE_ADJ5,           0x00001000 },
-          //     { AUD_DMD_RA_DDS,          0x00c0d5ce },
-          { AUD_DEEMPHGAIN_R,        0x000023c2 },
-          { AUD_DEEMPHNUMER1_R,      0x0002a7bc },
-          { AUD_DEEMPHNUMER2_R,      0x0003023e },
-          { AUD_DEEMPHDENOM1_R,      0x0000f3d0 },
-          { AUD_DEEMPHDENOM2_R,      0x00000000 },
-          { AUD_DEEMPHDENOM2_R,      0x00000000 },
-          { AUD_ERRLOGPERIOD_R,      0x00000fff },
-          { AUD_ERRINTRPTTHSHLD1_R,  0x000003ff },
-          { AUD_ERRINTRPTTHSHLD2_R,  0x000000ff },
-          { AUD_ERRINTRPTTHSHLD3_R,  0x0000003f },
-          { AUD_POLYPH80SCALEFAC,    0x00000003 },
-          { AUD_PDF_DDS_CNST_BYTE2,  0x06 },
-          { AUD_PDF_DDS_CNST_BYTE1,  0x82 },
-          { AUD_PDF_DDS_CNST_BYTE0,  0x16 },
-          { AUD_QAM_MODE,            0x05 },
-          { AUD_PDF_DDS_CNST_BYTE0,  0x12 },
-          { AUD_PHACC_FREQ_8MSB,     0x3a },
-          { AUD_PHACC_FREQ_8LSB,     0x93 },
-            { /* end of list */ },
-        };
-
-        dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
-
-        if (!stereo) {
-               // FM mono
-               set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+       { AUD_RATE_ADJ1,           0x00000010 },
+       { AUD_RATE_ADJ2,           0x00000040 },
+       { AUD_RATE_ADJ3,           0x00000100 },
+       { AUD_RATE_ADJ4,           0x00000400 },
+       { AUD_RATE_ADJ5,           0x00001000 },
+       //     { AUD_DMD_RA_DDS,          0x00c0d5ce },
+       { AUD_DEEMPHGAIN_R,        0x000023c2 },
+       { AUD_DEEMPHNUMER1_R,      0x0002a7bc },
+       { AUD_DEEMPHNUMER2_R,      0x0003023e },
+       { AUD_DEEMPHDENOM1_R,      0x0000f3d0 },
+       { AUD_DEEMPHDENOM2_R,      0x00000000 },
+       { AUD_DEEMPHDENOM2_R,      0x00000000 },
+       { AUD_ERRLOGPERIOD_R,      0x00000fff },
+       { AUD_ERRINTRPTTHSHLD1_R,  0x000003ff },
+       { AUD_ERRINTRPTTHSHLD2_R,  0x000000ff },
+       { AUD_ERRINTRPTTHSHLD3_R,  0x0000003f },
+       { AUD_POLYPH80SCALEFAC,    0x00000003 },
+       { AUD_PDF_DDS_CNST_BYTE2,  0x06 },
+       { AUD_PDF_DDS_CNST_BYTE1,  0x82 },
+       { AUD_PDF_DDS_CNST_BYTE0,  0x16 },
+       { AUD_QAM_MODE,            0x05 },
+       { AUD_PDF_DDS_CNST_BYTE0,  0x12 },
+       { AUD_PHACC_FREQ_8MSB,     0x3a },
+       { AUD_PHACC_FREQ_8LSB,     0x93 },
+       { /* end of list */ },
+       };
+
+       dprintk("%s (status: devel), stereo : %d\n",__FUNCTION__,stereo);
+
+       if (!stereo) {
+       /* FM Mono */
+       set_audio_start(core, SEL_A2);
                set_audio_registers(core, pal_i_fm_mono);
-        } else {
-               // Nicam Stereo
-               set_audio_start(core, 0x0010, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+               set_audio_finish(core, EN_DMTRX_SUMDIFF | EN_A2_FORCE_MONO1);
+       } else {
+       /* Nicam Stereo */
+       set_audio_start(core, SEL_NICAM);
                set_audio_registers(core, pal_i_nicam);
-        }
-        set_audio_finish(core);
+               set_audio_finish(core, EN_DMTRX_LR | EN_DMTRX_BYPASS | EN_NICAM_AUTO_STEREO);
+       }
 }
 
-static void set_audio_standard_A2(struct cx88_core *core)
+static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
 {
-       /* from dscaler cvs */
        static const struct rlist a2_common[] = {
-               { AUD_PDF_DDS_CNST_BYTE2,     0x06 },
-               { AUD_PDF_DDS_CNST_BYTE1,     0x82 },
-               { AUD_PDF_DDS_CNST_BYTE0,     0x12 },
-               { AUD_QAM_MODE,               0x05 },
-               { AUD_PHACC_FREQ_8MSB,        0x34 },
-               { AUD_PHACC_FREQ_8LSB,        0x4c },
-
-               { AUD_RATE_ADJ1,        0x00001000 },
-               { AUD_RATE_ADJ2,        0x00002000 },
-               { AUD_RATE_ADJ3,        0x00003000 },
-               { AUD_RATE_ADJ4,        0x00004000 },
-               { AUD_RATE_ADJ5,        0x00005000 },
-               { AUD_THR_FR,           0x00000000 },
-               { AAGC_HYST,            0x0000001a },
-               { AUD_PILOT_BQD_1_K0,   0x0000755b },
-               { AUD_PILOT_BQD_1_K1,   0x00551340 },
-               { AUD_PILOT_BQD_1_K2,   0x006d30be },
-               { AUD_PILOT_BQD_1_K3,   0xffd394af },
-               { AUD_PILOT_BQD_1_K4,   0x00400000 },
-               { AUD_PILOT_BQD_2_K0,   0x00040000 },
-               { AUD_PILOT_BQD_2_K1,   0x002a4841 },
-               { AUD_PILOT_BQD_2_K2,   0x00400000 },
-               { AUD_PILOT_BQD_2_K3,   0x00000000 },
-               { AUD_PILOT_BQD_2_K4,   0x00000000 },
-               { AUD_MODE_CHG_TIMER,   0x00000040 },
-               { AUD_START_TIMER,      0x00000200 },
-               { AUD_AFE_12DB_EN,      0x00000000 },
-               { AUD_CORDIC_SHIFT_0,   0x00000007 },
-               { AUD_CORDIC_SHIFT_1,   0x00000007 },
-               { AUD_DEEMPH0_G0,       0x00000380 },
-               { AUD_DEEMPH1_G0,       0x00000380 },
-               { AUD_DCOC_0_SRC,       0x0000001a },
-               { AUD_DCOC0_SHIFT,      0x00000000 },
-               { AUD_DCOC_0_SHIFT_IN0, 0x0000000a },
-               { AUD_DCOC_0_SHIFT_IN1, 0x00000008 },
-               { AUD_DCOC_PASS_IN,     0x00000003 },
-               { AUD_IIR3_0_SEL,       0x00000021 },
-               { AUD_DN2_AFC,          0x00000002 },
-               { AUD_DCOC_1_SRC,       0x0000001b },
-               { AUD_DCOC1_SHIFT,      0x00000000 },
-               { AUD_DCOC_1_SHIFT_IN0, 0x0000000a },
-               { AUD_DCOC_1_SHIFT_IN1, 0x00000008 },
-               { AUD_IIR3_1_SEL,       0x00000023 },
-               { AUD_RDSI_SEL,         0x00000017 },
-               { AUD_RDSI_SHIFT,       0x00000000 },
-               { AUD_RDSQ_SEL,         0x00000017 },
-               { AUD_RDSQ_SHIFT,       0x00000000 },
-               { AUD_POLYPH80SCALEFAC, 0x00000001 },
+       {AUD_ERRLOGPERIOD_R,            0x00000064},
+       {AUD_ERRINTRPTTHSHLD1_R,        0x00000fff},
+       {AUD_ERRINTRPTTHSHLD2_R,        0x0000001f},
+       {AUD_ERRINTRPTTHSHLD3_R,        0x0000000f},
+       {AUD_PDF_DDS_CNST_BYTE2,        0x06},
+       {AUD_PDF_DDS_CNST_BYTE1,        0x82},
+       {AUD_PDF_DDS_CNST_BYTE0,        0x12},
+       {AUD_QAM_MODE,                  0x05},
+       {AUD_PHACC_FREQ_8MSB,           0x34},
+       {AUD_PHACC_FREQ_8LSB,           0x4c},
+       {AUD_RATE_ADJ1,                 0x00000100},
+       {AUD_RATE_ADJ2,                 0x00000200},
+       {AUD_RATE_ADJ3,                 0x00000300},
+       {AUD_RATE_ADJ4,                 0x00000400},
+       {AUD_RATE_ADJ5,                 0x00000500},
+       {AUD_THR_FR,                    0x00000000},
+       {AAGC_HYST,                     0x0000001a},
+       {AUD_PILOT_BQD_1_K0,            0x0000755b},
+       {AUD_PILOT_BQD_1_K1,            0x00551340},
+       {AUD_PILOT_BQD_1_K2,            0x006d30be},
+       {AUD_PILOT_BQD_1_K3,            0xffd394af},
+       {AUD_PILOT_BQD_1_K4,            0x00400000},
+       {AUD_PILOT_BQD_2_K0,            0x00040000},
+       {AUD_PILOT_BQD_2_K1,            0x002a4841},
+       {AUD_PILOT_BQD_2_K2,            0x00400000},
+       {AUD_PILOT_BQD_2_K3,            0x00000000},
+       {AUD_PILOT_BQD_2_K4,            0x00000000},
+       {AUD_MODE_CHG_TIMER,            0x00000040},
+       {AUD_AFE_12DB_EN,               0x00000001},
+       {AUD_CORDIC_SHIFT_0,            0x00000007},
+       {AUD_CORDIC_SHIFT_1,            0x00000007},
+       {AUD_DEEMPH0_G0,                0x00000380},
+       {AUD_DEEMPH1_G0,                0x00000380},
+       {AUD_DCOC_0_SRC,                0x0000001a},
+       {AUD_DCOC0_SHIFT,               0x00000000},
+       {AUD_DCOC_0_SHIFT_IN0,          0x0000000a},
+       {AUD_DCOC_0_SHIFT_IN1,          0x00000008},
+       {AUD_DCOC_PASS_IN,              0x00000003},
+       {AUD_IIR3_0_SEL,                0x00000021},
+       {AUD_DN2_AFC,                   0x00000002},
+       {AUD_DCOC_1_SRC,                0x0000001b},
+       {AUD_DCOC1_SHIFT,               0x00000000},
+       {AUD_DCOC_1_SHIFT_IN0,          0x0000000a},
+       {AUD_DCOC_1_SHIFT_IN1,          0x00000008},
+       {AUD_IIR3_1_SEL,                0x00000023},
+       {AUD_RDSI_SEL,                  0x00000017},
+       {AUD_RDSI_SHIFT,                0x00000000},
+       {AUD_RDSQ_SEL,                  0x00000017},
+       {AUD_RDSQ_SHIFT,                0x00000000},
+       {AUD_PLL_INT,                   0x0000001e},
+       {AUD_PLL_DDS,                   0x00000000},
+       {AUD_PLL_FRAC,                  0x0000e542},
+       {AUD_POLYPH80SCALEFAC,          0x00000001},
+       {AUD_START_TIMER,               0x00000000},
+       { /* end of list */ },
+       };
 
+       static const struct rlist a2_bg[] = {
+       {AUD_DMD_RA_DDS,                0x002a4f2f},
+       {AUD_C1_UP_THR,                 0x00007000},
+       {AUD_C1_LO_THR,                 0x00005400},
+       {AUD_C2_UP_THR,                 0x00005400},
+       {AUD_C2_LO_THR,                 0x00003000},
                { /* end of list */ },
        };
 
-       static const struct rlist a2_table1[] = {
-               // PAL-BG
-               { AUD_DMD_RA_DDS,       0x002a73bd },
-               { AUD_C1_UP_THR,        0x00007000 },
-               { AUD_C1_LO_THR,        0x00005400 },
-               { AUD_C2_UP_THR,        0x00005400 },
-               { AUD_C2_LO_THR,        0x00003000 },
+       static const struct rlist a2_dk[] = {
+       {AUD_DMD_RA_DDS,                0x002a4f2f},
+       {AUD_C1_UP_THR,                 0x00007000},
+       {AUD_C1_LO_THR,                 0x00005400},
+       {AUD_C2_UP_THR,                 0x00005400},
+       {AUD_C2_LO_THR,                 0x00003000},
+       {AUD_DN0_FREQ,                  0x00003a1c},
+       {AUD_DN2_FREQ,                  0x0000d2e0},
                { /* end of list */ },
        };
-       static const struct rlist a2_table2[] = {
-               // PAL-DK
-               { AUD_DMD_RA_DDS,       0x002a73bd },
-               { AUD_C1_UP_THR,        0x00007000 },
-               { AUD_C1_LO_THR,        0x00005400 },
-               { AUD_C2_UP_THR,        0x00005400 },
-               { AUD_C2_LO_THR,        0x00003000 },
-               { AUD_DN0_FREQ,         0x00003a1c },
-               { AUD_DN2_FREQ,         0x0000d2e0 },
+/* unknown, probably NTSC-M */
+       static const struct rlist a2_m[] = {
+       {AUD_DMD_RA_DDS,                0x002a0425},
+       {AUD_C1_UP_THR,                 0x00003c00},
+       {AUD_C1_LO_THR,                 0x00003000},
+       {AUD_C2_UP_THR,                 0x00006000},
+       {AUD_C2_LO_THR,                 0x00003c00},
+       {AUD_DEEMPH0_A0,                0x00007a80},
+       {AUD_DEEMPH1_A0,                0x00007a80},
+       {AUD_DEEMPH0_G0,                0x00001200},
+       {AUD_DEEMPH1_G0,                0x00001200},
+       {AUD_DN0_FREQ,                  0x0000283b},
+       {AUD_DN1_FREQ,                  0x00003418},
+       {AUD_DN2_FREQ,                  0x000029c7},
+       {AUD_POLY0_DDS_CONSTANT,        0x000a7540},
                { /* end of list */ },
        };
-       static const struct rlist a2_table3[] = {
-               // unknown, probably NTSC-M
-               { AUD_DMD_RA_DDS,       0x002a2873 },
-               { AUD_C1_UP_THR,        0x00003c00 },
-               { AUD_C1_LO_THR,        0x00003000 },
-               { AUD_C2_UP_THR,        0x00006000 },
-               { AUD_C2_LO_THR,        0x00003c00 },
-               { AUD_DN0_FREQ,         0x00002836 },
-               { AUD_DN1_FREQ,         0x00003418 },
-               { AUD_DN2_FREQ,         0x000029c7 },
-               { AUD_POLY0_DDS_CONSTANT, 0x000a7540 },
+
+       static const struct rlist a2_deemph50[] = {
+       {AUD_DEEMPH0_G0,                0x00000380},
+       {AUD_DEEMPH1_G0,                0x00000380},
+       {AUD_DEEMPHGAIN_R,              0x000011e1},
+       {AUD_DEEMPHNUMER1_R,            0x0002a7bc},
+       {AUD_DEEMPHNUMER2_R,            0x0003023c},
+       { /* end of list */ },
+       };
+
+       static const struct rlist a2_deemph75[] = {
+       {AUD_DEEMPH0_G0,                0x00000480},
+       {AUD_DEEMPH1_G0,                0x00000480},
+       {AUD_DEEMPHGAIN_R,              0x00009000},
+       {AUD_DEEMPHNUMER1_R,            0x000353de},
+       {AUD_DEEMPHNUMER2_R,            0x000001b1},
                { /* end of list */ },
        };
 
-       set_audio_start(core, 0x0004, EN_DMTRX_SUMDIFF | EN_A2_AUTO_STEREO);
+       set_audio_start(core, SEL_A2);
        set_audio_registers(core, a2_common);
        switch (core->tvaudio) {
        case WW_A2_BG:
                dprintk("%s PAL-BG A2 (status: known-good)\n",__FUNCTION__);
-               set_audio_registers(core, a2_table1);
+       set_audio_registers(core, a2_bg);
+       set_audio_registers(core, a2_deemph50);
                break;
        case WW_A2_DK:
                dprintk("%s PAL-DK A2 (status: known-good)\n",__FUNCTION__);
-               set_audio_registers(core, a2_table2);
+       set_audio_registers(core, a2_dk);
+       set_audio_registers(core, a2_deemph50);
                break;
        case WW_A2_M:
                dprintk("%s NTSC-M A2 (status: unknown)\n",__FUNCTION__);
-               set_audio_registers(core, a2_table3);
+       set_audio_registers(core, a2_m);
+       set_audio_registers(core, a2_deemph75);
                break;
        };
-       set_audio_finish(core);
+
+       mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
+       set_audio_finish(core, mode);
 }
 
 static void set_audio_standard_EIAJ(struct cx88_core *core)
@@ -635,9 +658,9 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
        };
        dprintk("%s (status: unknown)\n",__FUNCTION__);
 
-       set_audio_start(core, 0x0002, EN_EIAJ_AUTO_STEREO);
+       set_audio_start(core, SEL_EIAJ);
        set_audio_registers(core, eiaj);
-       set_audio_finish(core);
+       set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
 }
 
 static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph)
@@ -683,7 +706,7 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type
        };
 
        dprintk("%s (status: unknown)\n",__FUNCTION__);
-       set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
+       set_audio_start(core, SEL_FMRADIO);
 
        switch (deemph)
        {
@@ -700,7 +723,7 @@ static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type
                        break;
        }
 
-       set_audio_finish(core);
+       set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
 }
 
 /* ----------------------------------------------------------- */
@@ -709,7 +732,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
 {
        switch (core->tvaudio) {
        case WW_BTSC:
-               set_audio_standard_BTSC(core,0);
+               set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
                break;
        case WW_NICAM_BGDKL:
                set_audio_standard_NICAM_L(core,0);
@@ -720,7 +743,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
        case WW_A2_BG:
        case WW_A2_DK:
        case WW_A2_M:
-               set_audio_standard_A2(core);
+       set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
                break;
        case WW_EIAJ:
                set_audio_standard_EIAJ(core);
@@ -734,7 +757,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
        case WW_NONE:
        default:
                printk("%s/0: unknown tv audio mode [%d]\n",
-                      core->name, core->tvaudio);
+               core->name, core->tvaudio);
                break;
        }
        return;
@@ -769,6 +792,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
                        aud_ctl_names[cx_read(AUD_CTL) & 63]);
        core->astat = reg;
 
+/* TODO
+       Reading from AUD_STATUS is not enough
+       for auto-detecting sap/dual-fm/nicam.
+       Add some code here later.
+*/
+
+# if 0
        t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
                V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
        t->rxsubchans = V4L2_TUNER_SUB_MONO;
@@ -779,7 +809,7 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
                t->capability = V4L2_TUNER_CAP_STEREO |
                        V4L2_TUNER_CAP_SAP;
                t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-               if (1 == pilot) {
+               if (1 == pilot) {
                        /* SAP */
                        t->rxsubchans |= V4L2_TUNER_SUB_SAP;
                }
@@ -787,13 +817,13 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
        case WW_A2_BG:
        case WW_A2_DK:
        case WW_A2_M:
-               if (1 == pilot) {
+               if (1 == pilot) {
                        /* stereo */
                        t->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
                        if (0 == mode)
                                t->audmode = V4L2_TUNER_MODE_STEREO;
                }
-               if (2 == pilot) {
+               if (2 == pilot) {
                        /* dual language -- FIXME */
                        t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
                        t->audmode = V4L2_TUNER_MODE_LANG1;
@@ -805,16 +835,17 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
                        t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
                }
                break;
-        case WW_SYSTEM_L_AM:
-                if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
-                        t->audmode = V4L2_TUNER_MODE_STEREO;
+       case WW_SYSTEM_L_AM:
+               if (0x0 == mode && !(cx_read(AUD_INIT) & 0x04)) {
+                       t->audmode = V4L2_TUNER_MODE_STEREO;
                        t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
                }
-                break ;
+               break ;
        default:
                /* nothing */
                break;
        }
+# endif
        return;
 }
 
@@ -835,16 +866,16 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
        case WW_BTSC:
                switch (mode) {
                case V4L2_TUNER_MODE_MONO:
-                       ctl  = EN_BTSC_FORCE_MONO;
-                       mask = 0x3f;
+                       set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
                        break;
-               case V4L2_TUNER_MODE_SAP:
-                       ctl  = EN_BTSC_FORCE_SAP;
-                       mask = 0x3f;
+               case V4L2_TUNER_MODE_LANG1:
+                       set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+                       break;
+               case V4L2_TUNER_MODE_LANG2:
+                       set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
                        break;
                case V4L2_TUNER_MODE_STEREO:
-                       ctl  = EN_BTSC_AUTO_STEREO;
-                       mask = 0x3f;
+                       set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
                        break;
                }
                break;
@@ -854,16 +885,13 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
                switch (mode) {
                case V4L2_TUNER_MODE_MONO:
                case V4L2_TUNER_MODE_LANG1:
-                       ctl  = EN_A2_FORCE_MONO1;
-                       mask = 0x3f;
+               set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
                        break;
                case V4L2_TUNER_MODE_LANG2:
-                       ctl  = EN_A2_AUTO_MONO2;
-                       mask = 0x3f;
+               set_audio_standard_A2(core, EN_A2_FORCE_MONO2);
                        break;
                case V4L2_TUNER_MODE_STEREO:
-                       ctl  = EN_A2_AUTO_STEREO | EN_DMTRX_SUMR;
-                       mask = 0x8bf;
+               set_audio_standard_A2(core, EN_A2_FORCE_STEREO);
                        break;
                }
                break;
index 320d57888bbd942764df6a7059122fe909dbe5fa..9bc6c89955816fa3d58f122c5382c06e2c0e5757 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
index 5f58c103198afb02047d90012dcdd158fa58ddcd..3dbc074fb515a10c62783e1bda568b63a8a1c596 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88-video.c,v 1.82 2005/07/22 05:13:34 mkrufky Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * video4linux video interface
@@ -66,7 +65,7 @@ module_param(vid_limit,int,0644);
 MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
 
 #define dprintk(level,fmt, arg...)     if (video_debug >= level) \
-       printk(KERN_DEBUG "%s/0: " fmt, dev->core->name , ## arg)
+       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
 
 /* ------------------------------------------------------------------ */
 
@@ -326,22 +325,23 @@ static const int CX8800_CTLS = ARRAY_SIZE(cx8800_ctls);
 
 static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
 {
+       struct cx88_core *core = dev->core;
        if (fh->resources & bit)
                /* have it already allocated */
                return 1;
 
        /* is it free? */
-       down(&dev->lock);
+       down(&core->lock);
        if (dev->resources & bit) {
                /* no, someone else uses it */
-               up(&dev->lock);
+               up(&core->lock);
                return 0;
        }
        /* it's free, grab it */
        fh->resources  |= bit;
        dev->resources |= bit;
        dprintk(1,"res: get %d\n",bit);
-       up(&dev->lock);
+       up(&core->lock);
        return 1;
 }
 
@@ -360,27 +360,29 @@ int res_locked(struct cx8800_dev *dev, unsigned int bit)
 static
 void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
 {
+       struct cx88_core *core = dev->core;
        if ((fh->resources & bits) != bits)
                BUG();
 
-       down(&dev->lock);
+       down(&core->lock);
        fh->resources  &= ~bits;
        dev->resources &= ~bits;
        dprintk(1,"res: put %d\n",bits);
-       up(&dev->lock);
+       up(&core->lock);
 }
 
 /* ------------------------------------------------------------------ */
 
-static int video_mux(struct cx8800_dev *dev, unsigned int input)
+/* static int video_mux(struct cx8800_dev *dev, unsigned int input) */
+static int video_mux(struct cx88_core *core, unsigned int input)
 {
-       struct cx88_core *core = dev->core;
+       /* struct cx88_core *core = dev->core; */
 
        dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
                input, INPUT(input)->vmux,
                INPUT(input)->gpio0,INPUT(input)->gpio1,
                INPUT(input)->gpio2,INPUT(input)->gpio3);
-       dev->core->input = input;
+       core->input = input;
        cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input)->vmux << 14);
        cx_write(MO_GP3_IO, INPUT(input)->gpio3);
        cx_write(MO_GP0_IO, INPUT(input)->gpio0);
@@ -413,9 +415,9 @@ static int start_video_dma(struct cx8800_dev    *dev,
        struct cx88_core *core = dev->core;
 
        /* setup fifo + format */
-       cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH21],
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
                                buf->bpl, buf->risc.dma);
-       cx88_set_scale(dev->core, buf->vb.width, buf->vb.height, buf->vb.field);
+       cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
        cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
 
        /* reset counter */
@@ -424,6 +426,14 @@ static int start_video_dma(struct cx8800_dev    *dev,
 
        /* enable irqs */
        cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01);
+
+       /* Enables corresponding bits at PCI_INT_STAT:
+               bits 0 to 4: video, audio, transport stream, VIP, Host
+               bit 7: timer
+               bits 8 and 9: DMA complete for: SRC, DST
+               bits 10 and 11: BERR signal asserted for RISC: RD, WR
+               bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
+        */
        cx_set(MO_VID_INTMSK, 0x0f0011);
 
        /* enable capture */
@@ -431,7 +441,7 @@ static int start_video_dma(struct cx8800_dev    *dev,
 
        /* start dma */
        cx_set(MO_DEV_CNTRL2, (1<<5));
-       cx_set(MO_VID_DMACNTRL, 0x11);
+       cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
 
        return 0;
 }
@@ -455,6 +465,7 @@ static int stop_video_dma(struct cx8800_dev    *dev)
 static int restart_video_queue(struct cx8800_dev    *dev,
                               struct cx88_dmaqueue *q)
 {
+       struct cx88_core *core = dev->core;
        struct cx88_buffer *buf, *prev;
        struct list_head *item;
 
@@ -524,12 +535,13 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
 {
        struct cx8800_fh   *fh  = q->priv_data;
        struct cx8800_dev  *dev = fh->dev;
+       struct cx88_core *core = dev->core;
        struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
        int rc, init_buffer = 0;
 
        BUG_ON(NULL == fh->fmt);
-       if (fh->width  < 48 || fh->width  > norm_maxw(dev->core->tvnorm) ||
-           fh->height < 32 || fh->height > norm_maxh(dev->core->tvnorm))
+       if (fh->width  < 48 || fh->width  > norm_maxw(core->tvnorm) ||
+           fh->height < 32 || fh->height > norm_maxh(core->tvnorm))
                return -EINVAL;
        buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
@@ -609,6 +621,7 @@ buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        struct cx88_buffer    *prev;
        struct cx8800_fh      *fh   = vq->priv_data;
        struct cx8800_dev     *dev  = fh->dev;
+       struct cx88_core      *core = dev->core;
        struct cx88_dmaqueue  *q    = &dev->vidq;
 
        /* add jump to stopper */
@@ -701,6 +714,7 @@ static int video_open(struct inode *inode, struct file *file)
 {
        int minor = iminor(inode);
        struct cx8800_dev *h,*dev = NULL;
+       struct cx88_core *core;
        struct cx8800_fh *fh;
        struct list_head *list;
        enum v4l2_buf_type type = 0;
@@ -725,6 +739,8 @@ static int video_open(struct inode *inode, struct file *file)
        if (NULL == dev)
                return -ENODEV;
 
+       core = dev->core;
+
        dprintk(1,"open minor=%d radio=%d type=%s\n",
                minor,radio,v4l2_type_names[type]);
 
@@ -755,17 +771,16 @@ static int video_open(struct inode *inode, struct file *file)
                            fh);
 
        if (fh->radio) {
-               struct cx88_core *core = dev->core;
                int board = core->board;
                dprintk(1,"video_open: setting radio device\n");
                cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3);
                cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0);
                cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1);
                cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2);
-               dev->core->tvaudio = WW_FM;
+               core->tvaudio = WW_FM;
                cx88_set_tvaudio(core);
                cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
-               cx88_call_i2c_clients(dev->core,AUDC_SET_RADIO,NULL);
+               cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL);
        }
 
         return 0;
@@ -857,6 +872,9 @@ static int video_release(struct inode *inode, struct file *file)
        videobuf_mmap_free(&fh->vbiq);
        file->private_data = NULL;
        kfree(fh);
+
+       cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
        return 0;
 }
 
@@ -870,9 +888,10 @@ video_mmap(struct file *file, struct vm_area_struct * vma)
 
 /* ------------------------------------------------------------------ */
 
-static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
+/* static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
+static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
 {
-       struct cx88_core *core = dev->core;
+       /* struct cx88_core *core = dev->core; */
        struct cx88_ctrl *c = NULL;
        u32 value;
        int i;
@@ -898,9 +917,10 @@ static int get_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
        return 0;
 }
 
-static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
+/* static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl) */
+static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
 {
-       struct cx88_core *core = dev->core;
+       /* struct cx88_core *core = dev->core; */
        struct cx88_ctrl *c = NULL;
         u32 v_sat_value;
        u32 value;
@@ -913,9 +933,9 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
                return -EINVAL;
 
        if (ctl->value < c->v.minimum)
-               return -ERANGE;
+               ctl->value = c->v.minimum;
        if (ctl->value > c->v.maximum)
-               return -ERANGE;
+               ctl->value = c->v.maximum;
        switch (ctl->id) {
        case V4L2_CID_AUDIO_BALANCE:
                value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
@@ -946,7 +966,8 @@ static int set_control(struct cx8800_dev *dev, struct v4l2_control *ctl)
        return 0;
 }
 
-static void init_controls(struct cx8800_dev *dev)
+/* static void init_controls(struct cx8800_dev *dev) */
+static void init_controls(struct cx88_core *core)
 {
        static struct v4l2_control mute = {
                .id    = V4L2_CID_AUDIO_MUTE,
@@ -969,11 +990,11 @@ static void init_controls(struct cx8800_dev *dev)
                .value = 0x80,
        };
 
-       set_control(dev,&mute);
-       set_control(dev,&volume);
-       set_control(dev,&hue);
-       set_control(dev,&contrast);
-       set_control(dev,&brightness);
+       set_control(core,&mute);
+       set_control(core,&volume);
+       set_control(core,&hue);
+       set_control(core,&contrast);
+       set_control(core,&brightness);
 }
 
 /* ------------------------------------------------------------------ */
@@ -1004,6 +1025,8 @@ static int cx8800_g_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
 static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
                          struct v4l2_format *f)
 {
+       struct cx88_core *core = dev->core;
+
        switch (f->type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        {
@@ -1016,8 +1039,8 @@ static int cx8800_try_fmt(struct cx8800_dev *dev, struct cx8800_fh *fh,
                        return -EINVAL;
 
                field = f->fmt.pix.field;
-               maxw  = norm_maxw(dev->core->tvnorm);
-               maxh  = norm_maxh(dev->core->tvnorm);
+               maxw  = norm_maxw(core->tvnorm);
+               maxh  = norm_maxh(core->tvnorm);
 
                if (V4L2_FIELD_ANY == field) {
                        field = (f->fmt.pix.height > maxh/2)
@@ -1101,12 +1124,14 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
        if (video_debug > 1)
                cx88_print_ioctl(core->name,cmd);
        switch (cmd) {
+
+       /* --- capabilities ------------------------------------------ */
        case VIDIOC_QUERYCAP:
        {
                struct v4l2_capability *cap = arg;
 
                memset(cap,0,sizeof(*cap));
-                strcpy(cap->driver, "cx8800");
+               strcpy(cap->driver, "cx8800");
                strlcpy(cap->card, cx88_boards[core->board].name,
                        sizeof(cap->card));
                sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
@@ -1116,12 +1141,128 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                        V4L2_CAP_READWRITE     |
                        V4L2_CAP_STREAMING     |
                        V4L2_CAP_VBI_CAPTURE   |
+                       V4L2_CAP_VIDEO_OVERLAY |
                        0;
                if (UNSET != core->tuner_type)
                        cap->capabilities |= V4L2_CAP_TUNER;
                return 0;
        }
 
+       /* --- capture ioctls ---------------------------------------- */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *f = arg;
+               enum v4l2_buf_type type;
+               unsigned int index;
+
+               index = f->index;
+               type  = f->type;
+               switch (type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (index >= ARRAY_SIZE(formats))
+                               return -EINVAL;
+                       memset(f,0,sizeof(*f));
+                       f->index = index;
+                       f->type  = type;
+                       strlcpy(f->description,formats[index].name,sizeof(f->description));
+                       f->pixelformat = formats[index].fourcc;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               return 0;
+       }
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *f = arg;
+               return cx8800_g_fmt(dev,fh,f);
+       }
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *f = arg;
+               return cx8800_s_fmt(dev,fh,f);
+       }
+       case VIDIOC_TRY_FMT:
+       {
+               struct v4l2_format *f = arg;
+               return cx8800_try_fmt(dev,fh,f);
+       }
+
+       /* --- streaming capture ------------------------------------- */
+       case VIDIOCGMBUF:
+       {
+               struct video_mbuf *mbuf = arg;
+               struct videobuf_queue *q;
+               struct v4l2_requestbuffers req;
+               unsigned int i;
+
+               q = get_queue(fh);
+               memset(&req,0,sizeof(req));
+               req.type   = q->type;
+               req.count  = 8;
+               req.memory = V4L2_MEMORY_MMAP;
+               err = videobuf_reqbufs(q,&req);
+               if (err < 0)
+                       return err;
+               memset(mbuf,0,sizeof(*mbuf));
+               mbuf->frames = req.count;
+               mbuf->size   = 0;
+               for (i = 0; i < mbuf->frames; i++) {
+                       mbuf->offsets[i]  = q->bufs[i]->boff;
+                       mbuf->size       += q->bufs[i]->bsize;
+               }
+               return 0;
+       }
+       case VIDIOC_REQBUFS:
+               return videobuf_reqbufs(get_queue(fh), arg);
+
+       case VIDIOC_QUERYBUF:
+               return videobuf_querybuf(get_queue(fh), arg);
+
+       case VIDIOC_QBUF:
+               return videobuf_qbuf(get_queue(fh), arg);
+
+       case VIDIOC_DQBUF:
+               return videobuf_dqbuf(get_queue(fh), arg,
+                                       file->f_flags & O_NONBLOCK);
+
+       case VIDIOC_STREAMON:
+       {
+               int res = get_ressource(fh);
+
+               if (!res_get(dev,fh,res))
+                       return -EBUSY;
+               return videobuf_streamon(get_queue(fh));
+       }
+       case VIDIOC_STREAMOFF:
+       {
+               int res = get_ressource(fh);
+
+               err = videobuf_streamoff(get_queue(fh));
+               if (err < 0)
+                       return err;
+               res_free(dev,fh,res);
+               return 0;
+       }
+
+       default:
+               return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl );
+       }
+       return 0;
+}
+
+int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+                  struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl)
+{
+       int err;
+
+       if (video_debug > 1)
+               cx88_print_ioctl(core->name,cmd);
+       printk( KERN_INFO "CORE IOCTL: 0x%x\n", cmd );
+       cx88_print_ioctl(core->name,cmd);
+       dprintk( 1, "CORE IOCTL: 0x%x\n", cmd );
+
+       switch (cmd) {
        /* ---------- tv norms ---------- */
        case VIDIOC_ENUMSTD:
        {
@@ -1156,9 +1297,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                if (i == ARRAY_SIZE(tvnorms))
                        return -EINVAL;
 
-               down(&dev->lock);
-               cx88_set_tvnorm(dev->core,&tvnorms[i]);
-               up(&dev->lock);
+               down(&core->lock);
+               cx88_set_tvnorm(core,&tvnorms[i]);
+               up(&core->lock);
                return 0;
        }
 
@@ -1199,7 +1340,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
        {
                unsigned int *i = arg;
 
-               *i = dev->core->input;
+               *i = core->input;
                return 0;
        }
        case VIDIOC_S_INPUT:
@@ -1208,55 +1349,15 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
 
                if (*i >= 4)
                        return -EINVAL;
-               down(&dev->lock);
+               down(&core->lock);
                cx88_newstation(core);
-               video_mux(dev,*i);
-               up(&dev->lock);
+               video_mux(core,*i);
+               up(&core->lock);
                return 0;
        }
 
 
 
-       /* --- capture ioctls ---------------------------------------- */
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *f = arg;
-               enum v4l2_buf_type type;
-               unsigned int index;
-
-               index = f->index;
-               type  = f->type;
-               switch (type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (index >= ARRAY_SIZE(formats))
-                               return -EINVAL;
-                       memset(f,0,sizeof(*f));
-                       f->index = index;
-                       f->type  = type;
-                       strlcpy(f->description,formats[index].name,sizeof(f->description));
-                       f->pixelformat = formats[index].fourcc;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               return 0;
-       }
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format *f = arg;
-               return cx8800_g_fmt(dev,fh,f);
-       }
-       case VIDIOC_S_FMT:
-       {
-               struct v4l2_format *f = arg;
-               return cx8800_s_fmt(dev,fh,f);
-       }
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *f = arg;
-               return cx8800_try_fmt(dev,fh,f);
-       }
-
        /* --- controls ---------------------------------------------- */
        case VIDIOC_QUERYCTRL:
        {
@@ -1277,9 +1378,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                return 0;
        }
        case VIDIOC_G_CTRL:
-               return get_control(dev,arg);
+               return get_control(core,arg);
        case VIDIOC_S_CTRL:
-               return set_control(dev,arg);
+               return set_control(core,arg);
 
        /* --- tuner ioctls ------------------------------------------ */
        case VIDIOC_G_TUNER:
@@ -1323,10 +1424,11 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                if (UNSET == core->tuner_type)
                        return -EINVAL;
 
-               f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-               f->frequency = dev->freq;
+               /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+               f->type = radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+               f->frequency = core->freq;
 
-               cx88_call_i2c_clients(dev->core,VIDIOC_G_FREQUENCY,f);
+               cx88_call_i2c_clients(core,VIDIOC_G_FREQUENCY,f);
 
                return 0;
        }
@@ -1338,83 +1440,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
                        return -EINVAL;
                if (f->tuner != 0)
                        return -EINVAL;
-               if (0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)
+               if (0 == radio && f->type != V4L2_TUNER_ANALOG_TV)
                        return -EINVAL;
-               if (1 == fh->radio && f->type != V4L2_TUNER_RADIO)
+               if (1 == radio && f->type != V4L2_TUNER_RADIO)
                        return -EINVAL;
-               down(&dev->lock);
-               dev->freq = f->frequency;
+               down(&core->lock);
+               core->freq = f->frequency;
                cx88_newstation(core);
-               cx88_call_i2c_clients(dev->core,VIDIOC_S_FREQUENCY,f);
+               cx88_call_i2c_clients(core,VIDIOC_S_FREQUENCY,f);
 
                /* When changing channels it is required to reset TVAUDIO */
                msleep (10);
                cx88_set_tvaudio(core);
 
-               up(&dev->lock);
-               return 0;
-       }
-
-       /* --- streaming capture ------------------------------------- */
-       case VIDIOCGMBUF:
-       {
-               struct video_mbuf *mbuf = arg;
-               struct videobuf_queue *q;
-               struct v4l2_requestbuffers req;
-               unsigned int i;
-
-               q = get_queue(fh);
-               memset(&req,0,sizeof(req));
-               req.type   = q->type;
-               req.count  = 8;
-               req.memory = V4L2_MEMORY_MMAP;
-               err = videobuf_reqbufs(q,&req);
-               if (err < 0)
-                       return err;
-               memset(mbuf,0,sizeof(*mbuf));
-               mbuf->frames = req.count;
-               mbuf->size   = 0;
-               for (i = 0; i < mbuf->frames; i++) {
-                       mbuf->offsets[i]  = q->bufs[i]->boff;
-                       mbuf->size       += q->bufs[i]->bsize;
-               }
-               return 0;
-       }
-       case VIDIOC_REQBUFS:
-               return videobuf_reqbufs(get_queue(fh), arg);
-
-       case VIDIOC_QUERYBUF:
-               return videobuf_querybuf(get_queue(fh), arg);
-
-       case VIDIOC_QBUF:
-               return videobuf_qbuf(get_queue(fh), arg);
-
-       case VIDIOC_DQBUF:
-               return videobuf_dqbuf(get_queue(fh), arg,
-                                     file->f_flags & O_NONBLOCK);
-
-       case VIDIOC_STREAMON:
-       {
-               int res = get_ressource(fh);
-
-                if (!res_get(dev,fh,res))
-                       return -EBUSY;
-               return videobuf_streamon(get_queue(fh));
-       }
-       case VIDIOC_STREAMOFF:
-       {
-               int res = get_ressource(fh);
-
-               err = videobuf_streamoff(get_queue(fh));
-               if (err < 0)
-                       return err;
-               res_free(dev,fh,res);
+               up(&core->lock);
                return 0;
        }
 
        default:
                return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-                                                 video_do_ioctl);
+                                                 driver_ioctl);
        }
        return 0;
 }
@@ -1461,7 +1506,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                memset(t,0,sizeof(*t));
                strcpy(t->name, "Radio");
 
-               cx88_call_i2c_clients(dev->core,VIDIOC_G_TUNER,t);
+               cx88_call_i2c_clients(core,VIDIOC_G_TUNER,t);
                return 0;
        }
        case VIDIOC_ENUMINPUT:
@@ -1501,8 +1546,8 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                if (v->tuner) /* Only tuner 0 */
                        return -EINVAL;
 
-               cx88_call_i2c_clients(dev->core,VIDIOCSTUNER,v);
-                return 0;
+               cx88_call_i2c_clients(core,VIDIOCSTUNER,v);
+               return 0;
        }
        case VIDIOC_S_TUNER:
        {
@@ -1511,7 +1556,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
                if (0 != t->index)
                        return -EINVAL;
 
-               cx88_call_i2c_clients(dev->core,VIDIOC_S_TUNER,t);
+               cx88_call_i2c_clients(core,VIDIOC_S_TUNER,t);
 
                return 0;
        }
@@ -1569,7 +1614,7 @@ static void cx8800_vid_timeout(unsigned long data)
        struct cx88_buffer *buf;
        unsigned long flags;
 
-       cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
+       cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
 
        cx_clear(MO_VID_DMACNTRL, 0x11);
        cx_clear(VID_CAPTURE_CONTROL, 0x06);
@@ -1614,14 +1659,14 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
                printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
                cx_clear(MO_VID_DMACNTRL, 0x11);
                cx_clear(VID_CAPTURE_CONTROL, 0x06);
-               cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH21]);
+               cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
        }
 
        /* risc1 y */
        if (status & 0x01) {
                spin_lock(&dev->slock);
                count = cx_read(MO_VIDY_GPCNT);
-               cx88_wakeup(dev->core, &dev->vidq, count);
+               cx88_wakeup(core, &dev->vidq, count);
                spin_unlock(&dev->slock);
        }
 
@@ -1629,7 +1674,7 @@ static void cx8800_vid_irq(struct cx8800_dev *dev)
        if (status & 0x08) {
                spin_lock(&dev->slock);
                count = cx_read(MO_VBI_GPCNT);
-               cx88_wakeup(dev->core, &dev->vbiq, count);
+               cx88_wakeup(core, &dev->vbiq, count);
                spin_unlock(&dev->slock);
        }
 
@@ -1798,7 +1843,6 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
        }
 
        /* initialize driver struct */
-        init_MUTEX(&dev->lock);
        spin_lock_init(&dev->slock);
        core->tvnorm = tvnorms;
 
@@ -1835,6 +1879,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
                request_module("tuner");
        if (core->tda9887_conf)
                request_module("tda9887");
+
        /* register v4l devices */
        dev->video_dev = cx88_vdev_init(core,dev->pci,
                                        &cx8800_video_template,"video");
@@ -1878,11 +1923,11 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
        pci_set_drvdata(pci_dev,dev);
 
        /* initial device configuration */
-       down(&dev->lock);
-       init_controls(dev);
-       cx88_set_tvnorm(dev->core,tvnorms);
-       video_mux(dev,0);
-       up(&dev->lock);
+       down(&core->lock);
+       init_controls(core);
+       cx88_set_tvnorm(core,tvnorms);
+       video_mux(core,0);
+       up(&core->lock);
 
        /* start tvaudio thread */
        if (core->tuner_type != TUNER_ABSENT)
@@ -1902,14 +1947,15 @@ fail_free:
 static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
 {
         struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx88_core *core = dev->core;
 
        /* stop thread */
-       if (dev->core->kthread) {
-               kthread_stop(dev->core->kthread);
-               dev->core->kthread = NULL;
+       if (core->kthread) {
+               kthread_stop(core->kthread);
+               core->kthread = NULL;
        }
 
-       cx88_shutdown(dev->core); /* FIXME */
+       cx88_shutdown(core); /* FIXME */
        pci_disable_device(pci_dev);
 
        /* unregister stuff */
@@ -1921,7 +1967,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
        /* free memory */
        btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
        list_del(&dev->devlist);
-       cx88_core_put(dev->core,dev->pci);
+       cx88_core_put(core,dev->pci);
        kfree(dev);
 }
 
@@ -1945,7 +1991,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
        spin_unlock(&dev->slock);
 
        /* FIXME -- shutdown device */
-       cx88_shutdown(dev->core);
+       cx88_shutdown(core);
 
        pci_save_state(pci_dev);
        if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
@@ -1959,16 +2005,32 @@ static int cx8800_resume(struct pci_dev *pci_dev)
 {
        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
        struct cx88_core *core = dev->core;
+       int err;
 
        if (dev->state.disabled) {
-               pci_enable_device(pci_dev);
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       printk(KERN_ERR "%s: can't enable device\n",
+                                                      core->name);
+                       return err;
+               }
+
                dev->state.disabled = 0;
        }
-       pci_set_power_state(pci_dev, PCI_D0);
+       err= pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               printk(KERN_ERR "%s: can't enable device\n",
+                                      core->name);
+
+               pci_disable_device(pci_dev);
+               dev->state.disabled = 1;
+
+               return err;
+       }
        pci_restore_state(pci_dev);
 
        /* FIXME: re-initialize hardware */
-       cx88_reset(dev->core);
+       cx88_reset(core);
 
        /* restart video+vbi capture */
        spin_lock(&dev->slock);
@@ -2030,6 +2092,8 @@ static void cx8800_fini(void)
 module_init(cx8800_init);
 module_exit(cx8800_fini);
 
+EXPORT_SYMBOL(cx88_do_ioctl);
+
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
index da65dc92787cdd6218a5a9fc34e3f611a868b5e8..f48dd43535688f676ba7a9c2f28418e79377f068 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: cx88.h,v 1.70 2005/07/24 17:44:09 mkrufky Exp $
  *
  * v4l2 device driver for cx2388x based TV cards
  *
@@ -35,7 +34,7 @@
 #include "btcx-risc.h"
 #include "cx88-reg.h"
 
-#include <linux/utsname.h>
+#include <linux/version.h>
 #define CX88_VERSION_CODE KERNEL_VERSION(0,0,5)
 
 #ifndef TRUE
@@ -48,6 +47,9 @@
 
 #define CX88_MAXBOARDS 8
 
+/* Max number of inputs by card */
+#define MAX_CX88_INPUT 8
+
 /* ----------------------------------------------------------- */
 /* defines and enums                                           */
 
@@ -199,7 +201,7 @@ struct cx88_board {
        unsigned char           tuner_addr;
        unsigned char           radio_addr;
        int                     tda9887_conf;
-       struct cx88_input       input[8];
+       struct cx88_input       input[MAX_CX88_INPUT];
        struct cx88_input       radio;
        int                     blackbird:1;
        int                     dvb:1;
@@ -288,6 +290,11 @@ struct cx88_core {
 
        /* IR remote control state */
        struct cx88_IR             *ir;
+
+       struct semaphore           lock;
+
+       /* various v4l controls */
+       u32                        freq;
 };
 
 struct cx8800_dev;
@@ -323,8 +330,7 @@ struct cx8800_suspend_state {
 struct cx8800_dev {
        struct cx88_core           *core;
        struct list_head           devlist;
-        struct semaphore           lock;
-               spinlock_t                 slock;
+       spinlock_t                 slock;
 
        /* various device info */
        unsigned int               resources;
@@ -342,7 +348,6 @@ struct cx8800_dev {
        struct cx88_dmaqueue       vbiq;
 
        /* various v4l controls */
-       u32                        freq;
 
        /* other global state info */
        struct cx8800_suspend_state state;
@@ -350,14 +355,8 @@ struct cx8800_dev {
 
 /* ----------------------------------------------------------- */
 /* function 1: audio/alsa stuff                                */
+/* =============> moved to cx88-alsa.c <====================== */
 
-struct cx8801_dev {
-       struct cx88_core           *core;
-
-       /* pci i/o */
-       struct pci_dev             *pci;
-       unsigned char              pci_rev,pci_lat;
-};
 
 /* ----------------------------------------------------------- */
 /* function 2: mpeg stuff                                      */
@@ -373,8 +372,7 @@ struct cx8802_suspend_state {
 
 struct cx8802_dev {
        struct cx88_core           *core;
-        struct semaphore           lock;
-               spinlock_t                 slock;
+       spinlock_t                 slock;
 
        /* pci i/o */
        struct pci_dev             *pci;
@@ -553,8 +551,21 @@ void cx8802_fini_common(struct cx8802_dev *dev);
 int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state);
 int cx8802_resume_common(struct pci_dev *pci_dev);
 
+/* ----------------------------------------------------------- */
+/* cx88-video.c                                                */
+extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
+                               struct cx88_core *core, unsigned int cmd,
+                               void *arg, v4l2_kioctl driver_ioctl);
+
+/* ----------------------------------------------------------- */
+/* cx88-blackbird.c                                            */
+extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
+                               unsigned int cmd, void *arg);
+extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
+
 /*
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
index a565823330aaa29883f2a16f793a65b4cb7416ec..cf292da8fdd5752066411011319570b101b34c02 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $
  *
  * Copyright (c) 2003 Gerd Knorr
  * Copyright (c) 2003 Pavel Machek
@@ -354,6 +353,7 @@ static int ir_probe(struct device *dev)
                ir->input.id.vendor  = sub->core->pci->vendor;
                ir->input.id.product = sub->core->pci->device;
        }
+       ir->input.dev = &sub->core->pci->dev;
 
        if (ir->polling) {
                INIT_WORK(&ir->work, ir_work, ir);
index 1e273ff3f956802b9b664a62e3c9505e1e8efc49..67105b9804a2388888a66778c7523ec37ea4085d 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: ir-kbd-i2c.c,v 1.11 2005/07/07 16:42:11 mchehab Exp $
  *
  * keyboard input driver for i2c IR remote controls
  *
index ca02f6f14b000ece1f11eb12333da9b141dd2e90..f0d43fc2632f35db99f404d04cc42ef50a4f2818 100644 (file)
@@ -124,10 +124,14 @@ module_param(standard,         int, 0644);
 module_param(amsound,          int, 0644);
 module_param(dolby,            int, 0644);
 
+MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Simple, 2=Simpler");
 MODULE_PARM_DESC(once, "No continuous stereo monitoring");
 MODULE_PARM_DESC(debug, "Enable debug messages");
+MODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo");
 MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect");
 MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan");
+MODULE_PARM_DESC(dolby, "Activates Dolby processsing");
+
 
 MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
 MODULE_AUTHOR("Gerd Knorr");
@@ -1452,7 +1456,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
         client_template.addr = addr;
 
         if (-1 == msp3400c_reset(&client_template)) {
-                dprintk("msp3400: no chip found\n");
+                dprintk("msp34xx: no chip found\n");
                 return -1;
         }
 
@@ -1478,7 +1482,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
        if (-1 == msp3400c_reset(c)) {
                kfree(msp);
                kfree(c);
-               dprintk("msp3400: no chip found\n");
+               dprintk("msp34xx: no chip found\n");
                return -1;
        }
 
@@ -1488,7 +1492,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
        if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) {
                kfree(msp);
                kfree(c);
-               printk("msp3400: error while reading chip version\n");
+               dprintk("msp34xx: error while reading chip version\n");
                return -1;
        }
 
index 023f33056a4f82e7f3595be4932075d0797a9f2d..2d9ff40f0b09c0f6c8a3de98f60a82fe64c5c91e 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
  */
 
 #ifndef MSP3400_H
index 2fb7c2d1787a5a456282c2b70695e5d98678810e..972aa5e0aeef623f7ac8e02e6333949d02395246 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: mt20xx.c,v 1.5 2005/06/16 08:29:49 nsh Exp $
  *
  * i2c tv tuner chip device driver
  * controls microtune tuners, mt2032 + mt2050 at the moment.
@@ -494,6 +493,7 @@ int microtune_init(struct i2c_client *c)
        memset(buf,0,sizeof(buf));
        t->tv_freq    = NULL;
        t->radio_freq = NULL;
+       t->standby    = NULL;
        name = "unknown";
 
         i2c_master_send(c,buf,1);
diff --git a/drivers/media/video/rds.h b/drivers/media/video/rds.h
new file mode 100644 (file)
index 0000000..30337d0
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+
+    Types and defines needed for RDS. This is included by
+    saa6588.c and every driver (e.g. bttv-driver.c) that wants
+    to use the saa6588 module.
+
+    Instead of having a seperate rds.h, I'd prefer to include
+    this stuff in one of the already existing files like tuner.h
+
+    (c) 2005 by Hans J. Koch
+
+    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.
+
+*/
+
+#ifndef _RDS_H
+#define _RDS_H
+
+struct rds_command {
+       unsigned int  block_count;
+       int           result;
+       unsigned char *buffer;
+       struct file   *instance;
+       poll_table    *event_list;
+};
+
+#define RDS_CMD_OPEN   _IOW('R',1,int)
+#define RDS_CMD_CLOSE  _IOW('R',2,int)
+#define RDS_CMD_READ   _IOR('R',3,int)
+#define RDS_CMD_POLL   _IOR('R',4,int)
+
+#endif
+
+
+
+
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
new file mode 100644 (file)
index 0000000..1a657a7
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+    Driver for SAA6588 RDS decoder
+
+    (c) 2005 Hans J. Koch
+
+    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.
+*/
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+
+#include <media/id.h>
+
+#include "rds.h"
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {
+       0x20 >> 1,
+       0x22 >> 1,
+       I2C_CLIENT_END,
+};
+
+I2C_CLIENT_INSMOD;
+
+/* insmod options */
+static unsigned int debug = 0;
+static unsigned int xtal = 0;
+static unsigned int rbds = 0;
+static unsigned int plvl = 0;
+static unsigned int bufblocks = 100;
+
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "enable debug messages");
+MODULE_PARM(xtal, "i");
+MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
+MODULE_PARM(rbds, "i");
+MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
+MODULE_PARM(plvl, "i");
+MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
+MODULE_PARM(bufblocks, "i");
+MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
+
+MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
+MODULE_AUTHOR("Hans J. Koch <koch@hjk-az.de>");
+
+MODULE_LICENSE("GPL");
+
+/* ---------------------------------------------------------------------- */
+
+#define UNSET       (-1U)
+#define PREFIX      "saa6588: "
+#define dprintk     if (debug) printk
+
+struct saa6588 {
+       struct i2c_client client;
+       struct work_struct work;
+       struct timer_list timer;
+       spinlock_t lock;
+       unsigned char *buffer;
+       unsigned int buf_size;
+       unsigned int rd_index;
+       unsigned int wr_index;
+       unsigned int block_count;
+       unsigned char last_blocknum;
+       wait_queue_head_t read_queue;
+       int data_available_for_read;
+};
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * SAA6588 defines
+ */
+
+/* Initialization and mode control byte (0w) */
+
+/* bit 0+1 (DAC0/DAC1) */
+#define cModeStandard           0x00
+#define cModeFastPI             0x01
+#define cModeReducedRequest     0x02
+#define cModeInvalid            0x03
+
+/* bit 2 (RBDS) */
+#define cProcessingModeRDS      0x00
+#define cProcessingModeRBDS     0x04
+
+/* bit 3+4 (SYM0/SYM1) */
+#define cErrCorrectionNone      0x00
+#define cErrCorrection2Bits     0x08
+#define cErrCorrection5Bits     0x10
+#define cErrCorrectionNoneRBDS  0x18
+
+/* bit 5 (NWSY) */
+#define cSyncNormal             0x00
+#define cSyncRestart            0x20
+
+/* bit 6 (TSQD) */
+#define cSigQualityDetectOFF    0x00
+#define cSigQualityDetectON     0x40
+
+/* bit 7 (SQCM) */
+#define cSigQualityTriggered    0x00
+#define cSigQualityContinous    0x80
+
+/* Pause level and flywheel control byte (1w) */
+
+/* bits 0..5 (FEB0..FEB5) */
+#define cFlywheelMaxBlocksMask  0x3F
+#define cFlywheelDefault        0x20
+
+/* bits 6+7 (PL0/PL1) */
+#define cPauseLevel_11mV       0x00
+#define cPauseLevel_17mV        0x40
+#define cPauseLevel_27mV        0x80
+#define cPauseLevel_43mV        0xC0
+
+/* Pause time/oscillator frequency/quality detector control byte (1w) */
+
+/* bits 0..4 (SQS0..SQS4) */
+#define cQualityDetectSensMask  0x1F
+#define cQualityDetectDefault   0x0F
+
+/* bit 5 (SOSC) */
+#define cSelectOscFreqOFF      0x00
+#define cSelectOscFreqON       0x20
+
+/* bit 6+7 (PTF0/PTF1) */
+#define cOscFreq_4332kHz       0x00
+#define cOscFreq_8664kHz       0x40
+#define cOscFreq_12996kHz      0x80
+#define cOscFreq_17328kHz      0xC0
+
+/* ---------------------------------------------------------------------- */
+
+static int block_to_user_buf(struct saa6588 *s, unsigned char *user_buf)
+{
+       int i;
+
+       if (s->rd_index == s->wr_index) {
+               if (debug > 2)
+                       dprintk(PREFIX "Read: buffer empty.\n");
+               return 0;
+       }
+
+       if (debug > 2) {
+               dprintk(PREFIX "Read: ");
+               for (i = s->rd_index; i < s->rd_index + 3; i++)
+                       dprintk("0x%02x ", s->buffer[i]);
+       }
+
+       if (copy_to_user(user_buf, &s->buffer[s->rd_index], 3))
+               return -EFAULT;
+
+       s->rd_index += 3;
+       if (s->rd_index >= s->buf_size)
+               s->rd_index = 0;
+       s->block_count--;
+
+       if (debug > 2)
+               dprintk("%d blocks total.\n", s->block_count);
+
+       return 1;
+}
+
+static void read_from_buf(struct saa6588 *s, struct rds_command *a)
+{
+       unsigned long flags;
+
+       unsigned char *buf_ptr = a->buffer;     /* This is a user space buffer! */
+       unsigned int i;
+       unsigned int rd_blocks;
+
+       a->result = 0;
+       if (!a->buffer)
+               return;
+
+       while (!s->data_available_for_read) {
+               int ret = wait_event_interruptible(s->read_queue,
+                                            s->data_available_for_read);
+               if (ret == -ERESTARTSYS) {
+                       a->result = -EINTR;
+                       return;
+               }
+       }
+
+       spin_lock_irqsave(&s->lock, flags);
+       rd_blocks = a->block_count;
+       if (rd_blocks > s->block_count)
+               rd_blocks = s->block_count;
+
+       if (!rd_blocks)
+               return;
+
+       for (i = 0; i < rd_blocks; i++) {
+               if (block_to_user_buf(s, buf_ptr)) {
+                       buf_ptr += 3;
+                       a->result++;
+               } else
+                       break;
+       }
+       a->result *= 3;
+       s->data_available_for_read = (s->block_count > 0);
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf)
+{
+       unsigned int i;
+
+       if (debug > 3)
+               dprintk(PREFIX "New block: ");
+
+       for (i = 0; i < 3; ++i) {
+               if (debug > 3)
+                       dprintk("0x%02x ", blockbuf[i]);
+               s->buffer[s->wr_index] = blockbuf[i];
+               s->wr_index++;
+       }
+
+       if (s->wr_index >= s->buf_size)
+               s->wr_index = 0;
+
+       if (s->wr_index == s->rd_index) {
+               s->rd_index++;
+               if (s->rd_index >= s->buf_size)
+                       s->rd_index = 0;
+       } else
+               s->block_count++;
+
+       if (debug > 3)
+               dprintk("%d blocks total.\n", s->block_count);
+}
+
+static void saa6588_i2c_poll(struct saa6588 *s)
+{
+       unsigned long flags;
+       unsigned char tmpbuf[6];
+       unsigned char blocknum;
+       unsigned char tmp;
+
+       /* Although we only need 3 bytes, we have to read at least 6.
+          SAA6588 returns garbage otherwise */
+       if (6 != i2c_master_recv(&s->client, &tmpbuf[0], 6)) {
+               if (debug > 1)
+                       dprintk(PREFIX "read error!\n");
+               return;
+       }
+
+       blocknum = tmpbuf[0] >> 5;
+       if (blocknum == s->last_blocknum) {
+               if (debug > 3)
+                       dprintk("Saw block %d again.\n", blocknum);
+               return;
+       }
+
+       s->last_blocknum = blocknum;
+
+       /*
+          Byte order according to v4l2 specification:
+
+          Byte 0: Least Significant Byte of RDS Block
+          Byte 1: Most Significant Byte of RDS Block
+          Byte 2 Bit 7: Error bit. Indicates that an uncorrectable error
+          occurred during reception of this block.
+          Bit 6: Corrected bit. Indicates that an error was
+          corrected for this data block.
+          Bits 5-3: Received Offset. Indicates the offset received
+          by the sync system.
+          Bits 2-0: Offset Name. Indicates the offset applied to this data.
+
+          SAA6588 byte order is Status-MSB-LSB, so we have to swap the
+          first and the last of the 3 bytes block.
+        */
+
+       tmp = tmpbuf[2];
+       tmpbuf[2] = tmpbuf[0];
+       tmpbuf[0] = tmp;
+
+       tmp = blocknum;
+       tmp |= blocknum << 3;   /* Received offset == Offset Name (OK ?) */
+       if ((tmpbuf[2] & 0x03) == 0x03)
+               tmp |= 0x80;    /* uncorrectable error */
+       else if ((tmpbuf[2] & 0x03) != 0x00)
+               tmp |= 0x40;    /* corrected error */
+       tmpbuf[2] = tmp;        /* Is this enough ? Should we also check other bits ? */
+
+       spin_lock_irqsave(&s->lock, flags);
+       block_to_buf(s, tmpbuf);
+       spin_unlock_irqrestore(&s->lock, flags);
+       s->data_available_for_read = 1;
+       wake_up_interruptible(&s->read_queue);
+}
+
+static void saa6588_timer(unsigned long data)
+{
+       struct saa6588 *s = (struct saa6588 *)data;
+
+       schedule_work(&s->work);
+}
+
+static void saa6588_work(void *data)
+{
+       struct saa6588 *s = (struct saa6588 *)data;
+
+       saa6588_i2c_poll(s);
+       mod_timer(&s->timer, jiffies + HZ / 50);        /* 20 msec */
+}
+
+static int saa6588_configure(struct saa6588 *s)
+{
+       unsigned char buf[3];
+       int rc;
+
+       buf[0] = cSyncRestart;
+       if (rbds)
+               buf[0] |= cProcessingModeRBDS;
+
+       buf[1] = cFlywheelDefault;
+       switch (plvl) {
+       case 0:
+               buf[1] |= cPauseLevel_11mV;
+               break;
+       case 1:
+               buf[1] |= cPauseLevel_17mV;
+               break;
+       case 2:
+               buf[1] |= cPauseLevel_27mV;
+               break;
+       case 3:
+               buf[1] |= cPauseLevel_43mV;
+               break;
+       default:                /* nothing */
+               break;
+       }
+
+       buf[2] = cQualityDetectDefault | cSelectOscFreqON;
+
+       switch (xtal) {
+       case 0:
+               buf[2] |= cOscFreq_4332kHz;
+               break;
+       case 1:
+               buf[2] |= cOscFreq_8664kHz;
+               break;
+       case 2:
+               buf[2] |= cOscFreq_12996kHz;
+               break;
+       case 3:
+               buf[2] |= cOscFreq_17328kHz;
+               break;
+       default:                /* nothing */
+               break;
+       }
+
+       dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n",
+               buf[0], buf[1], buf[2]);
+
+       if (3 != (rc = i2c_master_send(&s->client, buf, 3)))
+               printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
+
+       return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct saa6588 *s;
+       client_template.adapter = adap;
+       client_template.addr = addr;
+
+       printk(PREFIX "chip found @ 0x%x\n", addr << 1);
+
+       if (NULL == (s = kmalloc(sizeof(*s), GFP_KERNEL)))
+               return -ENOMEM;
+
+       s->buf_size = bufblocks * 3;
+
+       if (NULL == (s->buffer = kmalloc(s->buf_size, GFP_KERNEL))) {
+               kfree(s);
+               return -ENOMEM;
+       }
+       s->client = client_template;
+       s->block_count = 0;
+       s->wr_index = 0;
+       s->rd_index = 0;
+       s->last_blocknum = 0xff;
+       init_waitqueue_head(&s->read_queue);
+       s->data_available_for_read = 0;
+       i2c_set_clientdata(&s->client, s);
+       i2c_attach_client(&s->client);
+
+       saa6588_configure(s);
+
+       /* start polling via eventd */
+       INIT_WORK(&s->work, saa6588_work, s);
+       init_timer(&s->timer);
+       s->timer.function = saa6588_timer;
+       s->timer.data = (unsigned long)s;
+       schedule_work(&s->work);
+
+       return 0;
+}
+
+static int saa6588_probe(struct i2c_adapter *adap)
+{
+#ifdef I2C_CLASS_TV_ANALOG
+       if (adap->class & I2C_CLASS_TV_ANALOG)
+               return i2c_probe(adap, &addr_data, saa6588_attach);
+#else
+       switch (adap->id) {
+       case I2C_ALGO_BIT | I2C_HW_B_BT848:
+       case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+       case I2C_ALGO_SAA7134:
+               return i2c_probe(adap, &addr_data, saa6588_attach);
+               break;
+       }
+#endif
+       return 0;
+}
+
+static int saa6588_detach(struct i2c_client *client)
+{
+       struct saa6588 *s = i2c_get_clientdata(client);
+
+       del_timer_sync(&s->timer);
+       flush_scheduled_work();
+
+       i2c_detach_client(client);
+       kfree(s->buffer);
+       kfree(s);
+       return 0;
+}
+
+static int saa6588_command(struct i2c_client *client, unsigned int cmd,
+                                                       void *arg)
+{
+       struct saa6588 *s = i2c_get_clientdata(client);
+       struct rds_command *a = (struct rds_command *)arg;
+
+       switch (cmd) {
+               /* --- open() for /dev/radio --- */
+       case RDS_CMD_OPEN:
+               a->result = 0;  /* return error if chip doesn't work ??? */
+               break;
+               /* --- close() for /dev/radio --- */
+       case RDS_CMD_CLOSE:
+               s->data_available_for_read = 1;
+               wake_up_interruptible(&s->read_queue);
+               a->result = 0;
+               break;
+               /* --- read() for /dev/radio --- */
+       case RDS_CMD_READ:
+               read_from_buf(s, a);
+               break;
+               /* --- poll() for /dev/radio --- */
+       case RDS_CMD_POLL:
+               a->result = 0;
+               if (s->data_available_for_read) {
+                       a->result |= POLLIN | POLLRDNORM;
+               }
+               poll_wait(a->instance, &s->read_queue, a->event_list);
+               break;
+
+       default:
+               /* nothing */
+               break;
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver driver = {
+       .owner = THIS_MODULE,
+       .name = "i2c saa6588 driver",
+       .id = -1,               /* FIXME */
+       .flags = I2C_DF_NOTIFY,
+       .attach_adapter = saa6588_probe,
+       .detach_client = saa6588_detach,
+       .command = saa6588_command,
+};
+
+static struct i2c_client client_template = {
+       .name = "saa6588",
+       .flags = I2C_CLIENT_ALLOW_USE,
+       .driver = &driver,
+};
+
+static int __init saa6588_init_module(void)
+{
+       return i2c_add_driver(&driver);
+}
+
+static void __exit saa6588_cleanup_module(void)
+{
+       i2c_del_driver(&driver);
+}
+
+module_init(saa6588_init_module);
+module_exit(saa6588_cleanup_module);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
index 88b71a20b602fa79985914735653766c0fbc37e9..acc7a4335e230ec3514ad06923fe0adba74f4af0 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-cards.c,v 1.80 2005/07/07 01:49:30 mkrufky Exp $
  *
  * device driver for philips saa7134 based TV cards
  * card-specific stuff.
@@ -1373,7 +1372,7 @@ struct saa7134_board saa7134_boards[] = {
                .inputs         = {{
                        .name = name_comp1,
                        .vmux = 1,
-                       .amux = LINE2,
+                       .amux = LINE1,
                },{
                        .name = name_tv,
                        .vmux = 3,
@@ -1382,7 +1381,7 @@ struct saa7134_board saa7134_boards[] = {
                },{
                        .name = name_svideo,
                        .vmux = 8,
-                       .amux = LINE2,
+                       .amux = LINE1,
                }},
                .radio = {
                        .name   = name_radio,
@@ -2001,6 +2000,115 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x000,
                },
        },
+       [SAA7134_BOARD_FLYTV_DIGIMATRIX] = {
+               .name           = "FlyTV mini Asus Digimatrix",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_LG_NTSC_TALN_MINI,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,             /* radio unconfirmed */
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_KWORLD_TERMINATOR] = {
+               /* Kworld V-Stream Studio TV Terminator */
+               /* "James Webb <jrwebb@qwest.net> */
+               .name           = "V-Stream Studio TV Terminator",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 1 << 21,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x0000000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x0000000,
+               },{
+                       .name = name_svideo,    /* S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x0000000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_YUAN_TUN900] = {
+               /* FIXME:
+                * S-Video and composite sources untested.
+                * Radio not working.
+                * Remote control not yet implemented.
+                * From : codemaster@webgeeks.be */
+               .name           = "Yuan TUN-900 (saa7135)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr= ADDR_UNSET,
+               .radio_addr= ADDR_UNSET,
+               .gpiomask       = 0x00010003,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x01,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x02,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE2,
+                       .gpio = 0x02,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+                       .gpio = 0x00010003,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
 };
 
 
@@ -2270,12 +2378,6 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x185b,
                .subdevice    = 0xc100,
                .driver_data  = SAA7134_BOARD_VIDEOMATE_TV_PVR,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1131,
-               .subdevice    = 0,
-               .driver_data  = SAA7134_BOARD_SABRENT_SBTTVFM,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -2346,6 +2448,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x4e42,
                .subdevice    = 0x0502,
                .driver_data  = SAA7134_BOARD_THYPHOON_DVBT_DUO_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x0210,         /* mini pci NTSC version */
+               .driver_data  = SAA7134_BOARD_FLYTV_DIGIMATRIX,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x0210,         /* mini pci PAL/SECAM version */
+               .driver_data  = SAA7134_BOARD_FLYTV_DIGIMATRIX,
 
        },{
                /* --- boards without eeprom + subsystem ID --- */
index 1dbe61755e9fc9e70693c99c8225d681ec37e00d..e5e36f3c6250cd534bc5cc79e30de08363ef16c4 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-core.c,v 1.39 2005/07/05 17:37:35 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * driver core
index 8be6a90358c84db36c0a4ca54bf6cb17d3d2e570..639ae51a052da0e74fb4606a5cb86e28f1dcaf7a 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-dvb.c,v 1.23 2005/07/24 22:12:47 mkrufky Exp $
  *
  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
@@ -29,7 +28,6 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/suspend.h>
-#include <linux/config.h>
 
 
 #include "saa7134-reg.h"
index c85348d0239fda3119b1852ee7777153d97cb6fe..77b627eb6483c38c259d7ea9c6f2614d3f8f7170 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $
  *
  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
index eae6b529713fe6cb3ff77673878fbcaeda776aae..711aa8e85fac3c801d87b5c45641cfb5d39560c9 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-i2c.c,v 1.22 2005/07/22 04:09:41 mkrufky Exp $
  *
  * device driver for philips saa7134 based TV cards
  * i2c interface support
index 213740122fe660cab906508e1081ba48eb483402..1f456c4d76f2dd90706811ce400de0eab48a2610 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-input.c,v 1.21 2005/06/22 23:37:34 nsh Exp $
  *
  * handle saa7134 IR remotes via linux kernel input layer.
  *
@@ -565,6 +564,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
                ir->dev.id.vendor  = dev->pci->vendor;
                ir->dev.id.product = dev->pci->device;
        }
+       ir->dev.dev = &dev->pci->dev;
 
        /* all done */
        dev->remote = ir;
index b5bede95dbf50e2c4570c217e7a662b61e3deb2b..c20630c82f1c4007e1de79b36a59e4faadaef101 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-oss.c,v 1.17 2005/06/28 23:41:47 mkrufky Exp $
  *
  * device driver for philips saa7134 based TV cards
  * oss dsp interface
index 87734f22af7d95f5224aeac9adabd4610688c800..ae0c7a165390a2f88fd1a7326eec51738c524710 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-reg.h,v 1.2 2004/09/15 16:15:24 kraxel Exp $
  *
  * philips saa7134 registers
  */
index 4dd9f1b2392834b18095ec689e1fdd8c2daa13a7..463885601ab43041cab0c83a14a98da20f280908 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-ts.c,v 1.15 2005/06/14 22:48:18 hhackmann Exp $
  *
  * device driver for philips saa7134 based TV cards
  * video4linux video interface
index eeafa5a71d2ba4615dd33c4f84f627783b7daeee..badf2f9e3072bf8befeaba2278551ee463903e60 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-tvaudio.c,v 1.30 2005/06/28 23:41:47 mkrufky Exp $
  *
  * device driver for philips saa7134 based TV cards
  * tv audio decoder (fm stereo, nicam, ...)
index 29e51cad2aafae5fd55708fe231705b5273ec338..f4aee0af80e19a942e7d10e28b7321cae709c34c 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * video4linux video interface
index a4c2f751d097976fe9448d0f6774ff94de06672b..35e5e85f669a4056534ddab47d70438045572557 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134-video.c,v 1.36 2005/06/28 23:41:47 mkrufky Exp $
  *
  * device driver for philips saa7134 based TV cards
  * video4linux video interface
@@ -1368,29 +1367,7 @@ static int video_release(struct inode *inode, struct file *file)
        saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
        saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
 
-       if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
-               u8 data[2];
-               int ret;
-               struct i2c_msg msg = {.addr=I2C_ADDR_TDA8290, .flags=0, .buf=data, .len = 2};
-               data[0] = 0x21;
-               data[1] = 0xc0;
-               ret = i2c_transfer(&dev->i2c_adap, &msg, 1);
-               if (ret != 1)
-                       printk(KERN_ERR "TDA8290 access failure\n");
-               msg.addr = I2C_ADDR_TDA8275;
-               data[0] = 0x30;
-               data[1] = 0xd0;
-               ret = i2c_transfer(&dev->i2c_adap, &msg, 1);
-               if (ret != 1)
-                       printk(KERN_ERR "TDA8275 access failure\n");
-               msg.addr = I2C_ADDR_TDA8290;
-               data[0] = 0x21;
-               data[1] = 0x80;
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               data[0] = 0x00;
-               data[1] = 0x02;
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-       }
+       saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL);
 
        /* free stuff */
        videobuf_mmap_free(&fh->cap);
index 2af0cb2a731b77b551752a79430dace51c0f1816..3ea09142ec9c44807b5fbb361647b0ceacb26ab7 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: saa7134.h,v 1.49 2005/07/13 17:25:25 mchehab Exp $
  *
  * v4l2 device driver for philips saa7134 based TV cards
  *
@@ -185,6 +184,9 @@ struct saa7134_format {
 #define SAA7134_BOARD_PHILIPS_TOUGH 61
 #define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
 #define SAA7134_BOARD_KWORLD_XPERT 63
+#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
+#define SAA7134_BOARD_KWORLD_TERMINATOR 65
+#define SAA7134_BOARD_YUAN_TUN900 66
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
index b57743571087b892d3a351f7c07d769d5976db90..d4497dbae05c7b641abaa617e9f17563847ecd0e 100644 (file)
@@ -2184,30 +2184,18 @@ static void release_saa(void)
                vfree(saa->vidbuf);
                vfree(saa->audbuf);
                vfree(saa->osdbuf);
-               if (saa->dmavid2)
-                       kfree((void *) saa->dmavid2);
+               kfree(saa->dmavid2);
                saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
                saa->dmavid2 = NULL;
-               if (saa->dmadebi)
-                       kfree((void *) saa->dmadebi);
-               if (saa->dmavid1)
-                       kfree((void *) saa->dmavid1);
-               if (saa->dmavid2)
-                       kfree((void *) saa->dmavid2);
-               if (saa->dmavid3)
-                       kfree((void *) saa->dmavid3);
-               if (saa->dmaa1in)
-                       kfree((void *) saa->dmaa1in);
-               if (saa->dmaa1out)
-                       kfree((void *) saa->dmaa1out);
-               if (saa->dmaa2in)
-                       kfree((void *) saa->dmaa2in);
-               if (saa->dmaa2out)
-                       kfree((void *) saa->dmaa2out);
-               if (saa->dmaRPS1)
-                       kfree((void *) saa->dmaRPS1);
-               if (saa->dmaRPS2)
-                       kfree((void *) saa->dmaRPS2);
+               kfree(saa->dmadebi);
+               kfree(saa->dmavid1);
+               kfree(saa->dmavid3);
+               kfree(saa->dmaa1in);
+               kfree(saa->dmaa1out);
+               kfree(saa->dmaa2in);
+               kfree(saa->dmaa2out);
+               kfree(saa->dmaRPS1);
+               kfree(saa->dmaRPS2);
                free_irq(saa->irq, saa);
                if (saa->saa7146_mem)
                        iounmap(saa->saa7146_mem);
index a8b6a8df5109d86eb8bd705c801bd0b17ca69e7b..c65f0c7680a2606578a4024a65a3ba784a539bb2 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: tda8290.c,v 1.15 2005/07/08 20:21:33 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * controls the philips tda8290+75 tuner chip combo.
@@ -9,6 +8,9 @@
 #include <linux/delay.h>
 #include <media/tuner.h>
 
+#define I2C_ADDR_TDA8290        0x4b
+#define I2C_ADDR_TDA8275        0x61
+
 /* ---------------------------------------------------------------------- */
 
 struct freq_entry {
@@ -75,10 +77,12 @@ static unsigned char i2c_init_tda8275[14] =         { 0x00, 0x00, 0x00, 0x00,
 static unsigned char i2c_set_VS[2] =           { 0x30, 0x6F };
 static unsigned char i2c_set_GP01_CF[2] =      { 0x20, 0x0B };
 static unsigned char i2c_tda8290_reset[2] =    { 0x00, 0x00 };
+static unsigned char i2c_tda8290_standby[2] =  { 0x00, 0x02 };
 static unsigned char i2c_gainset_off[2] =      { 0x28, 0x14 };
 static unsigned char i2c_gainset_on[2] =       { 0x28, 0x54 };
 static unsigned char i2c_agc3_00[2] =          { 0x80, 0x00 };
 static unsigned char i2c_agc2_BF[2] =          { 0x60, 0xBF };
+static unsigned char i2c_cb1_D0[2] =           { 0x30, 0xD0 };
 static unsigned char i2c_cb1_D2[2] =           { 0x30, 0xD2 };
 static unsigned char i2c_cb1_56[2] =           { 0x30, 0x56 };
 static unsigned char i2c_cb1_52[2] =           { 0x30, 0x52 };
@@ -117,6 +121,13 @@ static struct i2c_msg i2c_msg_epilog[] = {
        { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on },
 };
 
+static struct i2c_msg i2c_msg_standby[] = {
+       { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge },
+       { I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D0), i2c_cb1_D0 },
+       { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+       { I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_standby), i2c_tda8290_standby },
+};
+
 static int tda8290_tune(struct i2c_client *c)
 {
        struct tuner *t = i2c_get_clientdata(c);
@@ -205,6 +216,11 @@ static int has_signal(struct i2c_client *c)
        return (afc & 0x80)? 65535:0;
 }
 
+static void standby(struct i2c_client *c)
+{
+       i2c_transfer(c->adapter, i2c_msg_standby, ARRAY_SIZE(i2c_msg_standby));
+}
+
 int tda8290_init(struct i2c_client *c)
 {
        struct tuner *t = i2c_get_clientdata(c);
@@ -214,6 +230,7 @@ int tda8290_init(struct i2c_client *c)
        t->tv_freq    = set_tv_freq;
        t->radio_freq = set_radio_freq;
        t->has_signal = has_signal;
+       t->standby = standby;
 
        i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge));
        i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init));
index d60fc562aecdc4a1e2d05974cf976e11ec29aaf4..0456dda2624ddc5f487e0523c0926ee926c78dad 100644 (file)
@@ -23,6 +23,7 @@
       TDA9887 (world), TDA9885 (USA)
       Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
    - KNC One TV-Station RDS (saa7134)
+   - Hauppauge PVR-150/500 (possibly more)
 */
 
 
@@ -49,7 +50,7 @@ MODULE_LICENSE("GPL");
 struct tda9887 {
        struct i2c_client  client;
        v4l2_std_id        std;
-       unsigned int       radio;
+       enum tuner_mode    mode;
        unsigned int       config;
        unsigned int       pinnacle_id;
        unsigned int       using_v4l2;
@@ -196,7 +197,7 @@ static struct tvnorm tvnorms[] = {
                .b     = ( cNegativeFmTV  |
                           cQSS           ),
                .c     = ( cDeemphasisON  |
-                          cDeemphasis50  ),
+                          cDeemphasis75  ),
                .e     = ( cGating_36     |
                           cAudioIF_4_5   |
                           cVideoIF_45_75 ),
@@ -364,7 +365,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
        struct tvnorm *norm = NULL;
        int i;
 
-       if (t->radio) {
+       if (t->mode == T_RADIO) {
                if (t->radio_mode == V4L2_TUNER_MODE_MONO)
                        norm = &radio_mono;
                else
@@ -378,7 +379,7 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
                }
        }
        if (NULL == norm) {
-               dprintk(PREFIX "Oops: no tvnorm entry found\n");
+               dprintk(PREFIX "Unsupported tvnorm entry - audio muted\n");
                return -1;
        }
 
@@ -519,6 +520,12 @@ static int tda9887_fixup_std(struct tda9887 *t)
                        dprintk(PREFIX "insmod fixup: PAL => PAL-DK\n");
                        t->std = V4L2_STD_PAL_DK;
                        break;
+               case '-':
+                       /* default parameter, do nothing */
+                       break;
+               default:
+                       printk(PREFIX "pal= argument not recognised\n");
+                       break;
                }
        }
        if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
@@ -535,6 +542,12 @@ static int tda9887_fixup_std(struct tda9887 *t)
                        dprintk(PREFIX "insmod fixup: SECAM => SECAM-L\n");
                        t->std = V4L2_STD_SECAM_L;
                        break;
+               case '-':
+                       /* default parameter, do nothing */
+                       break;
+               default:
+                       printk(PREFIX "secam= argument not recognised\n");
+                       break;
                }
        }
        return 0;
@@ -569,6 +582,10 @@ static int tda9887_configure(struct tda9887 *t)
        tda9887_set_config(t,buf);
        tda9887_set_insmod(t,buf);
 
+       if (t->mode == T_STANDBY) {
+               buf[1] |= cForcedMuteAudioON;
+       }
+
 
        dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
                buf[1],buf[2],buf[3]);
@@ -653,10 +670,17 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
        /* --- configuration --- */
        case AUDC_SET_RADIO:
-               t->radio = 1;
+       {
+               t->mode = T_RADIO;
                tda9887_configure(t);
                break;
-
+       }
+       case TUNER_SET_STANDBY:
+       {
+               t->mode = T_STANDBY;
+               tda9887_configure(t);
+               break;
+       }
        case AUDC_CONFIG_PINNACLE:
        {
                int *i = arg;
@@ -689,7 +713,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
                struct video_channel *vc = arg;
 
                CHECK_V4L2;
-               t->radio = 0;
+               t->mode = T_ANALOG_TV;
                if (vc->norm < ARRAY_SIZE(map))
                        t->std = map[vc->norm];
                tda9887_fixup_std(t);
@@ -701,7 +725,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
                v4l2_std_id *id = arg;
 
                SWITCH_V4L2;
-               t->radio = 0;
+               t->mode = T_ANALOG_TV;
                t->std   = *id;
                tda9887_fixup_std(t);
                tda9887_configure(t);
@@ -713,14 +737,14 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
                SWITCH_V4L2;
                if (V4L2_TUNER_ANALOG_TV == f->type) {
-                       if (t->radio == 0)
+                       if (t->mode == T_ANALOG_TV)
                                return 0;
-                       t->radio = 0;
+                       t->mode = T_ANALOG_TV;
                }
                if (V4L2_TUNER_RADIO == f->type) {
-                       if (t->radio == 1)
+                       if (t->mode == T_RADIO)
                                return 0;
-                       t->radio = 1;
+                       t->mode = T_RADIO;
                }
                tda9887_configure(t);
                break;
@@ -735,7 +759,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
                };
                struct v4l2_tuner* tuner = arg;
 
-               if (t->radio) {
+               if (t->mode == T_RADIO) {
                        __u8 reg = 0;
                        tuner->afc=0;
                        if (1 == i2c_master_recv(&t->client,&reg,1))
@@ -747,7 +771,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
        {
                struct v4l2_tuner* tuner = arg;
 
-               if (t->radio) {
+               if (t->mode == T_RADIO) {
                        t->radio_mode = tuner->audmode;
                        tda9887_configure (t);
                }
index cebcc1fa68d12968e69dbd9297853fd9bb6f64bf..38bf50943798cee2cfd83c8db523c1c560242bb9 100644 (file)
@@ -2,7 +2,6 @@
  * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
  * I2C address is allways 0xC0.
  *
- * $Id: tea5767.c,v 1.27 2005/07/31 12:10:56 mchehab Exp $
  *
  * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
  * This code is placed under the terms of the GNU General Public License
@@ -205,11 +204,6 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
                    TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND;
        buffer[4] = 0;
 
-       if (t->mode == T_STANDBY) {
-               tuner_dbg("TEA5767 set to standby mode\n");
-               buffer[3] |= TEA5767_STDBY;
-       }
-
        if (t->audmode == V4L2_TUNER_MODE_MONO) {
                tuner_dbg("TEA5767 set to mono\n");
                buffer[2] |= TEA5767_MONO;
@@ -290,13 +284,31 @@ static int tea5767_stereo(struct i2c_client *c)
        return ((buffer[2] & TEA5767_STEREO_MASK) ? V4L2_TUNER_SUB_STEREO : 0);
 }
 
+static void tea5767_standby(struct i2c_client *c)
+{
+       unsigned char buffer[5];
+       struct tuner *t = i2c_get_clientdata(c);
+       unsigned div, rc;
+
+       div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
+       buffer[0] = (div >> 8) & 0x3f;
+       buffer[1] = div & 0xff;
+       buffer[2] = TEA5767_PORT1_HIGH;
+       buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
+                   TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
+       buffer[4] = 0;
+
+       if (5 != (rc = i2c_master_send(c, buffer, 5)))
+               tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
+}
+
 int tea5767_autodetection(struct i2c_client *c)
 {
        unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        int rc;
        struct tuner *t = i2c_get_clientdata(c);
 
-       if (7 != (rc = i2c_master_recv(c, buffer, 7))) {
+       if ((rc = i2c_master_recv(c, buffer, 7))< 5) {
                tuner_warn("It is not a TEA5767. Received %i bytes.\n", rc);
                return EINVAL;
        }
@@ -313,15 +325,10 @@ int tea5767_autodetection(struct i2c_client *c)
         *          bit 0   : internally set to 0
         *  Byte 5: bit 7:0 : == 0
         */
-       if (!((buffer[3] & 0x0f) == 0x00) && (buffer[4] == 0x00)) {
+       if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
                tuner_warn("Chip ID is not zero. It is not a TEA5767\n");
                return EINVAL;
        }
-       /* It seems that tea5767 returns 0xff after the 5th byte */
-       if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
-               tuner_warn("Returned more than 5 bytes. It is not a TEA5767\n");
-               return EINVAL;
-       }
 
        /* It seems that tea5767 returns 0xff after the 5th byte */
        if ((buffer[5] != 0xff) || (buffer[6] != 0xff)) {
@@ -337,14 +344,14 @@ int tea5767_tuner_init(struct i2c_client *c)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
-       tuner_info("type set to %d (%s)\n", t->type,
-                       "Philips TEA5767HN FM Radio");
+       tuner_info("type set to %d (%s)\n", t->type, "Philips TEA5767HN FM Radio");
        strlcpy(c->name, "tea5767", sizeof(c->name));
 
        t->tv_freq = set_tv_freq;
        t->radio_freq = set_radio_freq;
        t->has_signal = tea5767_signal;
        t->is_stereo = tea5767_stereo;
+       t->standby = tea5767_standby;
 
        return (0);
 }
index 3b1893c2ae3b136ffbf80d6fbf7122e53ce274ca..05572020af4d03a944bd317064272b2041d231d9 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: tuner-core.c,v 1.63 2005/07/28 18:19:55 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * core core, i.e. kernel interfaces, registering and so on
@@ -182,6 +181,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
                i2c_master_send(c, buffer, 4);
                default_tuner_init(c);
                break;
+       case TUNER_LG_TDVS_H062F:
+               /* Set the Auxiliary Byte. */
+               buffer[2] &= ~0x20;
+               buffer[2] |= 0x18;
+               buffer[3] = 0x20;
+               i2c_master_send(c, buffer, 4);
+               default_tuner_init(c);
+               break;
        default:
                default_tuner_init(c);
                break;
@@ -208,31 +215,31 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
-       if (tun_setup->addr == ADDR_UNSET) {
-               if (t->mode_mask & tun_setup->mode_mask)
+       if ((tun_setup->addr == ADDR_UNSET &&
+               (t->mode_mask & tun_setup->mode_mask)) ||
+               tun_setup->addr == c->addr) {
                        set_type(c, tun_setup->type, tun_setup->mode_mask);
-       } else if (tun_setup->addr == c->addr) {
-               set_type(c, tun_setup->type, tun_setup->mode_mask);
        }
 }
 
 static inline int check_mode(struct tuner *t, char *cmd)
 {
-       if (1 << t->mode & t->mode_mask) {
-               switch (t->mode) {
-               case V4L2_TUNER_RADIO:
-                       tuner_dbg("Cmd %s accepted for radio\n", cmd);
-                       break;
-               case V4L2_TUNER_ANALOG_TV:
-                       tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
-                       break;
-               case V4L2_TUNER_DIGITAL_TV:
-                       tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
-                       break;
-               }
-               return 0;
+       if ((1 << t->mode & t->mode_mask) == 0) {
+               return EINVAL;
+       }
+
+       switch (t->mode) {
+       case V4L2_TUNER_RADIO:
+               tuner_dbg("Cmd %s accepted for radio\n", cmd);
+               break;
+       case V4L2_TUNER_ANALOG_TV:
+               tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
+               break;
+       case V4L2_TUNER_DIGITAL_TV:
+               tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
+               break;
        }
-       return EINVAL;
+       return 0;
 }
 
 static char pal[] = "-";
@@ -274,6 +281,12 @@ static int tuner_fixup_std(struct tuner *t)
                        tuner_dbg ("insmod fixup: PAL => PAL-N\n");
                        t->std = V4L2_STD_PAL_N;
                        break;
+               case '-':
+                       /* default parameter, do nothing */
+                       break;
+               default:
+                       tuner_warn ("pal= argument not recognised\n");
+                       break;
                }
        }
        if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
@@ -290,6 +303,12 @@ static int tuner_fixup_std(struct tuner *t)
                        tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
                        t->std = V4L2_STD_SECAM_L;
                        break;
+               case '-':
+                       /* default parameter, do nothing */
+                       break;
+               default:
+                       tuner_warn ("secam= argument not recognised\n");
+                       break;
                }
        }
 
@@ -406,20 +425,18 @@ static int tuner_detach(struct i2c_client *client)
 
 static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
 {
-       if (mode != t->mode) {
-
-               t->mode = mode;
-               if (check_mode(t, cmd) == EINVAL) {
-                       t->mode = T_STANDBY;
-                       if (V4L2_TUNER_RADIO == mode) {
-                               set_tv_freq(client, 400 * 16);
-                       } else {
-                               set_radio_freq(client, 87.5 * 16000);
-                       }
-                       return EINVAL;
-               }
-       }
-       return 0;
+       if (mode == t->mode)
+               return 0;
+
+       t->mode = mode;
+
+       if (check_mode(t, cmd) == EINVAL) {
+               t->mode = T_STANDBY;
+               if (t->standby)
+                       t->standby (client);
+               return EINVAL;
+       }
+       return 0;
 }
 
 #define switch_v4l2()  if (!t->using_v4l2) \
@@ -453,6 +470,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        case AUDC_SET_RADIO:
                set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
                break;
+       case TUNER_SET_STANDBY:
+               {
+                       if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+                               return 0;
+                       if (t->standby)
+                               t->standby (client);
+                       break;
+               }
        case AUDC_CONFIG_PINNACLE:
                if (check_mode(t, "AUDC_CONFIG_PINNACLE") == EINVAL)
                        return 0;
index de0c93aeb75d8411835e8c9118f8eb7005002564..8edd73abe1d8cb356c639ac904fb870ed2473b4e 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: tuner-simple.c,v 1.43 2005/07/28 18:41:21 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * controls all those simple 4-control-bytes style tuners.
@@ -102,6 +101,7 @@ struct tunertype
  *     "no float in kernel" rule.
  */
 static struct tunertype tuners[] = {
+       /* 0-9 */
         { "Temic PAL (4002 FH5)", TEMIC, PAL,
          16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
        { "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I,
@@ -110,7 +110,6 @@ static struct tunertype tuners[] = {
          16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
        { "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM,
          16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
-
        { "NoTuner", NoTuner, NOTUNER,
          0,0,0x00,0x00,0x00,0x00,0x00},
        { "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL,
@@ -119,34 +118,34 @@ static struct tunertype tuners[] = {
          16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
        { "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
          16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
-
        { "Temic NTSC (4036 FY5)", TEMIC, NTSC,
          16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
         { "Alps HSBH1", TEMIC, NTSC,
          16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
-        { "Alps TSBE1",TEMIC,PAL,
+
+       /* 10-19 */
+        { "Alps TSBE1", TEMIC, PAL,
          16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
         { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */
          16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
-
         { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
          16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
         { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
          16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
        { "Temic PAL_BG (4006FH5)", TEMIC, PAL,
          16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-       { "Alps TSCH6",Alps,NTSC,
+       { "Alps TSCH6", Alps, NTSC,
          16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
-
-       { "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
+       { "Temic PAL_DK (4016 FY5)", TEMIC, PAL,
          16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
-       { "Philips NTSC_M (MK2)",Philips,NTSC,
+       { "Philips NTSC_M (MK2)", Philips, NTSC,
          16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
         { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
           16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
         { "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
           16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
 
+       /* 20-29 */
         { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL,
           16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
         { "Temic NTSC (4039 FR5)", TEMIC, NTSC,
@@ -155,7 +154,6 @@ static struct tunertype tuners[] = {
           16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
         { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL,
          16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-
        { "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
          16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
        { "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I,
@@ -164,25 +162,24 @@ static struct tunertype tuners[] = {
          16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
        { "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC,
          16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732},
-
        { "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL,
          16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
        { "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
          16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+
+       /* 30-39 */
        { "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
        { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
          16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
-
-       { "Samsung PAL TCPM9091PD27", Samsung, PAL,  /* from sourceforge v3tv */
+       { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */
           16*169,16*464,0xA0,0x90,0x30,0x8e,623},
-       { "MT20xx universal", Microtune,PAL|NTSC,
+       { "MT20xx universal", Microtune, PAL|NTSC,
          /* see mt20xx.c for details */ },
        { "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
           16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
        { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
           16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
-
        { "Temic NTSC (4136 FY5)", TEMIC, NTSC,
           16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
         { "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
@@ -192,42 +189,41 @@ static struct tunertype tuners[] = {
        { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC,
           16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
 
+       /* 40-49 */
        { "HITACHI V7-J180AT", HITACHI, NTSC,
          16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
        { "Philips PAL_MK (FI1216 MK)", Philips, PAL,
          16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
-       { "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
+       { "Philips 1236D ATSC/NTSC daul in", Philips, ATSC,
          16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732},
         { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC,
           16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
-
         { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC,
           16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
-       { "Microtune 4049 FM5",Microtune,PAL,
+       { "Microtune 4049 FM5", Microtune, PAL,
          16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
        { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
          16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
         { "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
           16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
-
         { "Tenna TNF 8831 BGFF)", Philips, PAL,
           16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
        { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC,
          16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732},
+
+       /* 50-59 */
         { "TCL 2002N", TCL, NTSC,
           16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732},
        { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL,
          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
-
        { "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC,
          16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
        { "Philips FQ1286", Philips, NTSC,
-         16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested
-       { "tda8290+75", Philips,PAL|NTSC,
+         16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, /* UHF band untested */
+       { "tda8290+75", Philips, PAL|NTSC,
          /* see tda8290.c for details */ },
        { "LG PAL (TAPE series)", LGINNOTEK, PAL,
           16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623},
-
        { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL,
          16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 },
        { "Philips FQ1236A MK4", Philips, NTSC,
@@ -237,6 +233,7 @@ static struct tunertype tuners[] = {
        { "Ymec TVision TVF-5533MF", Philips, NTSC,
          16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
 
+       /* 60-66 */
        { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
          16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
        { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL,
@@ -245,12 +242,12 @@ static struct tunertype tuners[] = {
           /* see tea5767.c for details */},
        { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL,
          16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 },
-
-       { "LG TDVS-H062F/TUA6034", LGINNOTEK, NTSC,
+       { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC,
          16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732},
-
        { "Ymec TVF66T5-B/DFF", Philips, PAL,
           16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623},
+       { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC,
+         16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 },
 };
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
@@ -471,6 +468,10 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
        case TUNER_LG_PAL_FM:
                buffer[3] = 0xa5;
                break;
+       case TUNER_MICROTUNE_4049FM5:
+               div = (20 * freq) / 16000 + (int)(33.3 * 20); /* IF 33.3 MHz */
+               buffer[3] = 0xa4;
+               break;
        default:
                buffer[3] = 0xa4;
                break;
@@ -497,6 +498,7 @@ int default_tuner_init(struct i2c_client *c)
        t->radio_freq = default_set_radio_freq;
        t->has_signal = tuner_signal;
        t->is_stereo  = tuner_stereo;
+       t->standby = NULL;
 
        return 0;
 }
index 258724b2d6d21a2001450996a3ac23541bc5afdb..1c31ef52f8639450ecae09b635937a9f43bfbd7f 100644 (file)
@@ -46,7 +46,17 @@ MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
 MODULE_LICENSE("GPL");
 
 #define UNSET    (-1U)
-#define dprintk  if (debug) printk
+
+#define tvaudio_info(fmt, arg...) do {\
+       printk(KERN_INFO "tvaudio %d-%04x: " fmt, \
+                       chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
+#define tvaudio_warn(fmt, arg...) do {\
+       printk(KERN_WARNING "tvaudio %d-%04x: " fmt, \
+                       chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
+#define tvaudio_dbg(fmt, arg...) do {\
+       if (debug) \
+               printk(KERN_INFO "tvaudio %d-%04x: " fmt, \
+                       chip->c.adapter->nr, chip->c.addr , ##arg); } while (0)
 
 /* ---------------------------------------------------------------------- */
 /* our structs                                                            */
@@ -162,23 +172,24 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
        unsigned char buffer[2];
 
        if (-1 == subaddr) {
-               dprintk("%s: chip_write: 0x%x\n", chip->c.name, val);
+               tvaudio_dbg("%s: chip_write: 0x%x\n",
+                       chip->c.name, val);
                chip->shadow.bytes[1] = val;
                buffer[0] = val;
                if (1 != i2c_master_send(&chip->c,buffer,1)) {
-                       printk(KERN_WARNING "%s: I/O error (write 0x%x)\n",
-                              chip->c.name, val);
+                       tvaudio_warn("%s: I/O error (write 0x%x)\n",
+                               chip->c.name, val);
                        return -1;
                }
        } else {
-               dprintk("%s: chip_write: reg%d=0x%x\n",
+               tvaudio_dbg("%s: chip_write: reg%d=0x%x\n",
                        chip->c.name, subaddr, val);
                chip->shadow.bytes[subaddr+1] = val;
                buffer[0] = subaddr;
                buffer[1] = val;
                if (2 != i2c_master_send(&chip->c,buffer,2)) {
-                       printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n",
-                              chip->c.name, subaddr, val);
+                       tvaudio_warn("%s: I/O error (write reg%d=0x%x)\n",
+                                               chip->c.name, subaddr, val);
                        return -1;
                }
        }
@@ -202,29 +213,30 @@ static int chip_read(struct CHIPSTATE *chip)
        unsigned char buffer;
 
        if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
-               printk(KERN_WARNING "%s: I/O error (read)\n", chip->c.name);
+               tvaudio_warn("%s: I/O error (read)\n",
+               chip->c.name);
                return -1;
        }
-       dprintk("%s: chip_read: 0x%x\n", chip->c.name, buffer);
+       tvaudio_dbg("%s: chip_read: 0x%x\n",chip->c.name,buffer);
        return buffer;
 }
 
 static int chip_read2(struct CHIPSTATE *chip, int subaddr)
 {
-        unsigned char write[1];
-        unsigned char read[1];
-        struct i2c_msg msgs[2] = {
-                { chip->c.addr, 0,        1, write },
-                { chip->c.addr, I2C_M_RD, 1, read  }
-        };
-        write[0] = subaddr;
+       unsigned char write[1];
+       unsigned char read[1];
+       struct i2c_msg msgs[2] = {
+               { chip->c.addr, 0,        1, write },
+               { chip->c.addr, I2C_M_RD, 1, read  }
+       };
+       write[0] = subaddr;
 
        if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
-               printk(KERN_WARNING "%s: I/O error (read2)\n", chip->c.name);
+               tvaudio_warn("%s: I/O error (read2)\n", chip->c.name);
                return -1;
        }
-       dprintk("%s: chip_read2: reg%d=0x%x\n",
-               chip->c.name, subaddr, read[0]);
+       tvaudio_dbg("%s: chip_read2: reg%d=0x%x\n",
+                       chip->c.name,subaddr,read[0]);
        return read[0];
 }
 
@@ -236,17 +248,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
                return 0;
 
        /* update our shadow register set; print bytes if (debug > 0) */
-       dprintk("%s: chip_cmd(%s): reg=%d, data:",
-               chip->c.name, name, cmd->bytes[0]);
+       tvaudio_dbg("%s: chip_cmd(%s): reg=%d, data:",
+               chip->c.name,name,cmd->bytes[0]);
        for (i = 1; i < cmd->count; i++) {
-               dprintk(" 0x%x",cmd->bytes[i]);
+               if (debug)
+                       printk(" 0x%x",cmd->bytes[i]);
                chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
        }
-       dprintk("\n");
+       if (debug)
+               printk("\n");
 
        /* send data to the chip */
        if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) {
-               printk(KERN_WARNING "%s: I/O error (%s)\n", chip->c.name, name);
+               tvaudio_warn("%s: I/O error (%s)\n", chip->c.name, name);
                return -1;
        }
        return 0;
@@ -261,19 +275,19 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
 
 static void chip_thread_wake(unsigned long data)
 {
-        struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+       struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
        wake_up_interruptible(&chip->wq);
 }
 
 static int chip_thread(void *data)
 {
        DECLARE_WAITQUEUE(wait, current);
-        struct CHIPSTATE *chip = data;
+       struct CHIPSTATE *chip = data;
        struct CHIPDESC  *desc = chiplist + chip->type;
 
        daemonize("%s", chip->c.name);
        allow_signal(SIGTERM);
-       dprintk("%s: thread started\n", chip->c.name);
+       tvaudio_dbg("%s: thread started\n", chip->c.name);
 
        for (;;) {
                add_wait_queue(&chip->wq, &wait);
@@ -285,7 +299,7 @@ static int chip_thread(void *data)
                try_to_freeze();
                if (chip->done || signal_pending(current))
                        break;
-               dprintk("%s: thread wakeup\n", chip->c.name);
+               tvaudio_dbg("%s: thread wakeup\n", chip->c.name);
 
                /* don't do anything for radio or if mode != auto */
                if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0)
@@ -298,8 +312,8 @@ static int chip_thread(void *data)
                mod_timer(&chip->wt, jiffies+2*HZ);
        }
 
-       dprintk("%s: thread exiting\n", chip->c.name);
-        complete_and_exit(&chip->texit, 0);
+       tvaudio_dbg("%s: thread exiting\n", chip->c.name);
+       complete_and_exit(&chip->texit, 0);
        return 0;
 }
 
@@ -309,9 +323,9 @@ static void generic_checkmode(struct CHIPSTATE *chip)
        int mode = desc->getmode(chip);
 
        if (mode == chip->prevmode)
-           return;
+               return;
 
-       dprintk("%s: thread checkmode\n", chip->c.name);
+       tvaudio_dbg("%s: thread checkmode\n", chip->c.name);
        chip->prevmode = mode;
 
        if (mode & VIDEO_SOUND_STEREO)
@@ -358,8 +372,8 @@ static int tda9840_getmode(struct CHIPSTATE *chip)
        if (val & TDA9840_ST_STEREO)
                mode |= VIDEO_SOUND_STEREO;
 
-       dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n",
-                val, mode);
+       tvaudio_dbg ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+               val, mode);
        return mode;
 }
 
@@ -654,8 +668,8 @@ static int tda9873_getmode(struct CHIPSTATE *chip)
                mode |= VIDEO_SOUND_STEREO;
        if (val & TDA9873_DUAL)
                mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
-       dprintk ("tda9873_getmode(): raw chip read: %d, return: %d\n",
-                val, mode);
+       tvaudio_dbg ("tda9873_getmode(): raw chip read: %d, return: %d\n",
+               val, mode);
        return mode;
 }
 
@@ -665,12 +679,12 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
        /*      int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
 
        if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) {
-               dprintk("tda9873_setmode(): external input\n");
+               tvaudio_dbg("tda9873_setmode(): external input\n");
                return;
        }
 
-       dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
-       dprintk("tda9873_setmode(): sw_data  = %d\n", sw_data);
+       tvaudio_dbg("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
+       tvaudio_dbg("tda9873_setmode(): sw_data  = %d\n", sw_data);
 
        switch (mode) {
        case VIDEO_SOUND_MONO:
@@ -691,7 +705,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
        }
 
        chip_write(chip, TDA9873_SW, sw_data);
-       dprintk("tda9873_setmode(): req. mode %d; chip_write: %d\n",
+       tvaudio_dbg("tda9873_setmode(): req. mode %d; chip_write: %d\n",
                mode, sw_data);
 }
 
@@ -828,9 +842,9 @@ static int tda9874a_setup(struct CHIPSTATE *chip)
        } else { /* dic == 0x07 */
                chip_write(chip, TDA9874A_AMCONR, 0xfb);
                chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
-               chip_write(chip, TDA9874A_AOSR, 0x00); // or 0x10
+               chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
        }
-       dprintk("tda9874a_setup(): %s [0x%02X].\n",
+       tvaudio_dbg("tda9874a_setup(): %s [0x%02X].\n",
                tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
        return 1;
 }
@@ -873,7 +887,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip)
                        mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
        }
 
-       dprintk("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
+       tvaudio_dbg("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
                 dsr, nsr, necr, mode);
        return mode;
 }
@@ -919,7 +933,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
                chip_write(chip, TDA9874A_AOSR, aosr);
                chip_write(chip, TDA9874A_MDACOSR, mdacosr);
 
-               dprintk("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+               tvaudio_dbg("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
                        mode, aosr, mdacosr);
 
        } else { /* dic == 0x07 */
@@ -954,7 +968,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
                chip_write(chip, TDA9874A_FMMR, fmmr);
                chip_write(chip, TDA9874A_AOSR, aosr);
 
-               dprintk("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
+               tvaudio_dbg("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
                        mode, fmmr, aosr);
        }
 }
@@ -968,10 +982,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
        if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
                return 0;
 
-       dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+       tvaudio_dbg("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
 
        if((dic == 0x11)||(dic == 0x07)) {
-               printk("tvaudio: found tda9874%s.\n", (dic == 0x11) ? "a":"h");
+               tvaudio_info("found tda9874%s.\n", (dic == 0x11) ? "a":"h");
                tda9874a_dic = dic;     /* remember device id. */
                return 1;
        }
@@ -1146,7 +1160,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
 /* ---------------------------------------------------------------------- */
 /* audio chip descriptions - defines+functions for TA8874Z                */
 
-// write 1st byte
+/* write 1st byte */
 #define TA8874Z_LED_STE        0x80
 #define TA8874Z_LED_BIL        0x40
 #define TA8874Z_LED_EXT        0x20
@@ -1156,21 +1170,22 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
 #define TA8874Z_MODE_SUB       0x02
 #define TA8874Z_MODE_MAIN      0x01
 
-// write 2nd byte
-//#define TA8874Z_TI   0x80  // test mode
+/* write 2nd byte */
+/*#define TA8874Z_TI   0x80  */ /* test mode */
 #define TA8874Z_SEPARATION     0x3f
 #define TA8874Z_SEPARATION_DEFAULT     0x10
 
-// read
+/* read */
 #define TA8874Z_B1     0x80
 #define TA8874Z_B0     0x40
 #define TA8874Z_CHAG_FLAG      0x20
 
-//        B1 B0
-// mono    L  H
-// stereo  L  L
-// BIL     H  L
-
+/*
+ *        B1 B0
+ * mono    L  H
+ * stereo  L  L
+ * BIL     H  L
+ */
 static int ta8874z_getmode(struct CHIPSTATE *chip)
 {
        int val, mode;
@@ -1182,7 +1197,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip)
        }else if (!(val & TA8874Z_B0)){
                mode |= VIDEO_SOUND_STEREO;
        }
-       //dprintk ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode);
+       /* tvaudio_dbg ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
        return mode;
 }
 
@@ -1195,7 +1210,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode)
 {
        int update = 1;
        audiocmd *t = NULL;
-       dprintk("ta8874z_setmode(): mode: 0x%02x\n", mode);
+       tvaudio_dbg("ta8874z_setmode(): mode: 0x%02x\n", mode);
 
        switch(mode){
        case VIDEO_SOUND_MONO:
@@ -1235,11 +1250,11 @@ static int tda9850  = 1;
 static int tda9855  = 1;
 static int tda9873  = 1;
 static int tda9874a = 1;
-static int tea6300  = 0;  // address clash with msp34xx
-static int tea6320  = 0;  // address clash with msp34xx
+static int tea6300  = 0;  /* address clash with msp34xx */
+static int tea6320  = 0;  /* address clash with msp34xx */
 static int tea6420  = 1;
 static int pic16c54 = 1;
-static int ta8874z  = 0;  // address clash with tda9840
+static int ta8874z  = 0;  /* address clash with tda9840 */
 
 module_param(tda8425, int, 0444);
 module_param(tda9840, int, 0444);
@@ -1441,7 +1456,7 @@ static struct CHIPDESC chiplist[] = {
        {
                .name       = "ta8874z",
                .id         = -1,
-               //.id         = I2C_DRIVERID_TA8874Z,
+               /*.id         = I2C_DRIVERID_TA8874Z, */
                .checkit    = ta8874z_checkit,
                .insmodopt  = &ta8874z,
                .addr_lo    = I2C_TDA9840 >> 1,
@@ -1476,7 +1491,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
        i2c_set_clientdata(&chip->c, chip);
 
        /* find description for the chip */
-       dprintk("tvaudio: chip found @ i2c-addr=0x%x\n", addr<<1);
+       tvaudio_dbg("chip found @ 0x%x\n", addr<<1);
        for (desc = chiplist; desc->name != NULL; desc++) {
                if (0 == *(desc->insmodopt))
                        continue;
@@ -1488,17 +1503,19 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
                break;
        }
        if (desc->name == NULL) {
-               dprintk("tvaudio: no matching chip description found\n");
+               tvaudio_dbg("no matching chip description found\n");
                return -EIO;
        }
-       printk("tvaudio: found %s @ 0x%x\n", desc->name, addr<<1);
-       dprintk("tvaudio: matches:%s%s%s.\n",
-               (desc->flags & CHIP_HAS_VOLUME)     ? " volume"      : "",
-               (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
-               (desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");
+       tvaudio_info("%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
+        if (desc->flags) {
+                tvaudio_dbg("matches:%s%s%s.\n",
+                        (desc->flags & CHIP_HAS_VOLUME)     ? " volume"      : "",
+                        (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
+                        (desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");
+        }
 
        /* fill required data structures */
-       strcpy(chip->c.name, desc->name);
+       strcpy(chip->c.name,desc->name);
        chip->type = desc-chiplist;
        chip->shadow.count = desc->registers+1;
         chip->prevmode = -1;
@@ -1534,7 +1551,7 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
                init_completion(&chip->texit);
                chip->tpid = kernel_thread(chip_thread,(void *)chip,0);
                if (chip->tpid < 0)
-                       printk(KERN_WARNING "%s: kernel_thread() failed\n",
+                       tvaudio_warn("%s: kernel_thread() failed\n",
                               chip->c.name);
                wake_up_interruptible(&chip->wq);
        }
@@ -1545,7 +1562,7 @@ static int chip_probe(struct i2c_adapter *adap)
 {
        /* don't attach on saa7146 based cards,
           because dedicated drivers are used */
-       if (adap->id == I2C_HW_SAA7146)
+       if ((adap->id == I2C_HW_SAA7146))
                return 0;
 #ifdef I2C_CLASS_TV_ANALOG
        if (adap->class & I2C_CLASS_TV_ANALOG)
@@ -1584,11 +1601,11 @@ static int chip_detach(struct i2c_client *client)
 static int chip_command(struct i2c_client *client,
                        unsigned int cmd, void *arg)
 {
-        __u16 *sarg = arg;
+       __u16 *sarg = arg;
        struct CHIPSTATE *chip = i2c_get_clientdata(client);
        struct CHIPDESC  *desc = chiplist + chip->type;
 
-       dprintk("%s: chip_command 0x%x\n", chip->c.name, cmd);
+       tvaudio_dbg("%s: chip_command 0x%x\n",chip->c.name,cmd);
 
        switch (cmd) {
        case AUDC_SET_INPUT:
@@ -1601,7 +1618,6 @@ static int chip_command(struct i2c_client *client,
                break;
 
        case AUDC_SET_RADIO:
-               dprintk(KERN_DEBUG "tvaudio: AUDC_SET_RADIO\n");
                chip->norm = VIDEO_MODE_RADIO;
                chip->watch_stereo = 0;
                /* del_timer(&chip->wt); */
@@ -1609,7 +1625,7 @@ static int chip_command(struct i2c_client *client,
 
        /* --- v4l ioctls --- */
        /* take care: bttv does userspace copying, we'll get a
-          kernel pointer here... */
+                                       kernel pointer here... */
        case VIDIOCGAUDIO:
        {
                struct video_audio *va = arg;
@@ -1643,9 +1659,9 @@ static int chip_command(struct i2c_client *client,
 
                if (desc->flags & CHIP_HAS_VOLUME) {
                        chip->left = (min(65536 - va->balance,32768) *
-                                     va->volume) / 32768;
+                               va->volume) / 32768;
                        chip->right = (min(va->balance,(__u16)32768) *
-                                      va->volume) / 32768;
+                               va->volume) / 32768;
                        chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
                        chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
                }
@@ -1667,17 +1683,16 @@ static int chip_command(struct i2c_client *client,
        {
                struct video_channel *vc = arg;
 
-               dprintk(KERN_DEBUG "tvaudio: VIDIOCSCHAN\n");
                chip->norm = vc->norm;
                break;
        }
        case VIDIOCSFREQ:
        {
-               chip->mode = 0; /* automatic */
+               chip->mode = 0; /* automatic */
                if (desc->checkmode) {
                        desc->setmode(chip,VIDEO_SOUND_MONO);
-                       if (chip->prevmode != VIDEO_SOUND_MONO)
-                               chip->prevmode = -1; /* reset previous mode */
+                       if (chip->prevmode != VIDEO_SOUND_MONO)
+                               chip->prevmode = -1; /* reset previous mode */
                        mod_timer(&chip->wt, jiffies+2*HZ);
                        /* the thread will call checkmode() later */
                }
@@ -1689,29 +1704,32 @@ static int chip_command(struct i2c_client *client,
 
 static struct i2c_driver driver = {
        .owner           = THIS_MODULE,
-        .name            = "generic i2c audio driver",
-        .id              = I2C_DRIVERID_TVAUDIO,
-        .flags           = I2C_DF_NOTIFY,
-        .attach_adapter  = chip_probe,
-        .detach_client   = chip_detach,
-        .command         = chip_command,
+       .name            = "generic i2c audio driver",
+       .id              = I2C_DRIVERID_TVAUDIO,
+       .flags           = I2C_DF_NOTIFY,
+       .attach_adapter  = chip_probe,
+       .detach_client   = chip_detach,
+       .command         = chip_command,
 };
 
 static struct i2c_client client_template =
 {
        .name       = "(unset)",
        .flags      = I2C_CLIENT_ALLOW_USE,
-        .driver     = &driver,
+       .driver     = &driver,
 };
 
 static int __init audiochip_init_module(void)
 {
        struct CHIPDESC  *desc;
-       printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
-       printk(KERN_INFO "tvaudio: known chips: ");
-       for (desc = chiplist; desc->name != NULL; desc++)
-               printk("%s%s", (desc == chiplist) ? "" : ",",desc->name);
-       printk("\n");
+
+       if (debug) {
+               printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
+               printk(KERN_INFO "tvaudio: known chips: ");
+               for (desc = chiplist; desc->name != NULL; desc++)
+                       printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name);
+               printk("\n");
+       }
 
        return i2c_add_driver(&driver);
 }
index 3c3356a01cc67e9dc3cf9b09114a3bd8e1485dcf..5344d5592199356a5f0601991134e2d455c870a7 100644 (file)
@@ -47,18 +47,21 @@ MODULE_LICENSE("GPL");
 
 static int debug = 0;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-2)");
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
 
 #define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown")
 
-#define dprintk(num, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(KERN_INFO "tveeprom: " args); \
-       } while (0)
+#define tveeprom_info(fmt, arg...) do {\
+       printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
+                        c->adapter->nr, c->addr , ##arg); } while (0)
+#define tveeprom_warn(fmt, arg...) do {\
+       printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \
+                        c->adapter->nr, c->addr , ##arg); } while (0)
+#define tveeprom_dbg(fmt, arg...) do {\
+       if (debug) \
+                printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
+                        c->adapter->nr, c->addr , ##arg); } while (0)
 
-#define TVEEPROM_KERN_ERR(args...) printk(KERN_ERR "tveeprom: " args);
-#define TVEEPROM_KERN_INFO(args...) printk(KERN_INFO "tveeprom: " args);
 
 /* ----------------------------------------------------------------------- */
 /* some hauppauge specific stuff                                           */
@@ -70,14 +73,14 @@ static struct HAUPPAUGE_TUNER_FMT
 }
 hauppauge_tuner_fmt[] =
 {
-       { 0x00000000, "unknown1" },
-       { 0x00000000, "unknown2" },
-       { 0x00000007, "PAL(B/G)" },
-       { 0x00001000, "NTSC(M)" },
-       { 0x00000010, "PAL(I)" },
-       { 0x00400000, "SECAM(L/L´)" },
-       { 0x00000e00, "PAL(D/K)" },
-       { 0x03000000, "ATSC Digital" },
+       { 0x00000000, " unknown1" },
+       { 0x00000000, " unknown2" },
+       { 0x00000007, " PAL(B/G)" },
+       { 0x00001000, " NTSC(M)" },
+       { 0x00000010, " PAL(I)" },
+       { 0x00400000, " SECAM(L/L')" },
+       { 0x00000e00, " PAL(D/K)" },
+       { 0x03000000, " ATSC Digital" },
 };
 
 /* This is the full list of possible tuners. Many thanks to Hauppauge for
@@ -152,13 +155,13 @@ hauppauge_tuner[] =
        { TUNER_MICROTUNE_4049FM5, "Microtune 4049 FM5"},
        { TUNER_ABSENT,        "LG TPI8NSR11F"},
        { TUNER_ABSENT,        "Microtune 4049 FM5 Alt I2C"},
-       { TUNER_ABSENT,        "Philips FQ1216ME MK3"},
+       { TUNER_PHILIPS_FM1216ME_MK3, "Philips FQ1216ME MK3"},
        { TUNER_ABSENT,        "Philips FI1236 MK3"},
        { TUNER_PHILIPS_FM1216ME_MK3, "Philips FM1216 ME MK3"},
-       { TUNER_ABSENT,        "Philips FM1236 MK3"},
+       { TUNER_PHILIPS_FM1236_MK3, "Philips FM1236 MK3"},
        { TUNER_ABSENT,        "Philips FM1216MP MK3"},
        /* 60-69 */
-       { TUNER_ABSENT,        "LG S001D MK3"},
+       { TUNER_PHILIPS_FM1216ME_MK3, "LG S001D MK3"},
        { TUNER_ABSENT,        "LG M001D MK3"},
        { TUNER_ABSENT,        "LG S701D MK3"},
        { TUNER_ABSENT,        "LG M701D MK3"},
@@ -167,7 +170,7 @@ hauppauge_tuner[] =
        { TUNER_ABSENT,        "Temic 4106FH5"},
        { TUNER_ABSENT,        "Philips FQ1216LMP MK3"},
        { TUNER_LG_NTSC_TAPE,  "LG TAPE H001F MK3"},
-       { TUNER_ABSENT,        "LG TAPE H701F MK3"},
+       { TUNER_LG_NTSC_TAPE,  "LG TAPE H701F MK3"},
        /* 70-79 */
        { TUNER_ABSENT,        "LG TALN H200T"},
        { TUNER_ABSENT,        "LG TALN H250T"},
@@ -183,8 +186,8 @@ hauppauge_tuner[] =
        { TUNER_ABSENT,        "Philips FQ1216LME MK3"},
        { TUNER_ABSENT,        "LG TAPC G701D"},
        { TUNER_LG_NTSC_NEW_TAPC, "LG TAPC H791F"},
-       { TUNER_ABSENT,        "TCL 2002MB 3"},
-       { TUNER_ABSENT,        "TCL 2002MI 3"},
+       { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MB 3"},
+       { TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
        { TUNER_TCL_2002N,     "TCL 2002N 6A"},
        { TUNER_ABSENT,        "Philips FQ1236 MK3"},
        { TUNER_ABSENT,        "Samsung TCPN 2121P30A"},
@@ -199,17 +202,51 @@ hauppauge_tuner[] =
        { TUNER_ABSENT,        "Philips FQ1236 MK5"},
        { TUNER_ABSENT,        "Unspecified"},
        { TUNER_LG_PAL_TAPE,   "LG PAL (TAPE Series)"},
+        { TUNER_ABSENT,        "Unspecified"},
+        { TUNER_TCL_2002N,     "TCL 2002N 5H"},
+       /* 100-103 */
+       { TUNER_ABSENT,        "Unspecified"},
+        { TUNER_TEA5767,       "Philips TEA5767HN FM Radio"},
+        { TUNER_ABSENT,        "Unspecified"},
+        { TUNER_PHILIPS_FM1236_MK3, "TCL MFNM05 4"},
 };
 
-static char *sndtype[] = {
-       "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C", "MSP3410D",
-       "MSP3415", "MSP3430", "MSP3438", "CS5331", "MSP3435", "MSP3440",
-       "MSP3445", "MSP3411", "MSP3416", "MSP3425",
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *audioIC[] = {
+        /* 0-4 */
+        "None", "TEA6300", "TEA6320", "TDA9850", "MSP3400C",
+        /* 5-9 */
+        "MSP3410D", "MSP3415", "MSP3430", "MSP3438", "CS5331",
+        /* 10-14 */
+        "MSP3435", "MSP3440", "MSP3445", "MSP3411", "MSP3416",
+        /* 15-19 */
+        "MSP3425", "MSP3451", "MSP3418", "Type 0x12", "OKI7716",
+        /* 20-24 */
+        "MSP4410", "MSP4420", "MSP4440", "MSP4450", "MSP4408",
+        /* 25-29 */
+        "MSP4418", "MSP4428", "MSP4448", "MSP4458", "Type 0x1d",
+        /* 30-34 */
+        "CX880", "CX881", "CX883", "CX882", "CX25840",
+        /* 35-38 */
+        "CX25841", "CX25842", "CX25843", "CX23418",
+};
 
-       "Type 0x10","Type 0x11","Type 0x12","Type 0x13",
-       "Type 0x14","Type 0x15","Type 0x16","Type 0x17",
-       "Type 0x18","MSP4418","Type 0x1a","MSP4448",
-       "Type 0x1c","Type 0x1d","Type 0x1e","Type 0x1f",
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *decoderIC[] = {
+        /* 0-4 */
+        "None", "BT815", "BT817", "BT819", "BT815A",
+        /* 5-9 */
+        "BT817A", "BT819A", "BT827", "BT829", "BT848",
+        /* 10-14 */
+        "BT848A", "BT849A", "BT829A", "BT827A", "BT878",
+        /* 15-19 */
+        "BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115",
+        /* 20-24 */
+        "CX880", "CX881", "CX883", "SAA7111", "SAA7113",
+        /* 25-29 */
+        "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
+        /* 30-31 */
+        "CX25843", "CX23418",
 };
 
 static int hasRadioTuner(int tunerType)
@@ -250,7 +287,8 @@ static int hasRadioTuner(int tunerType)
         return 0;
 }
 
-void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data)
+void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
+                                unsigned char *eeprom_data)
 {
        /* ----------------------------------------------
        ** The hauppauge eeprom format is tagged
@@ -260,10 +298,11 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
        ** if packet[0] & f8 == f8, then EOD and packet[1] == checksum
        **
        ** In our (ivtv) case we're interested in the following:
-       ** tuner type: tag [00].05 or [0a].01 (index into hauppauge_tuner)
-       ** tuner fmts: tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
-       ** radio:      tag [00].{last} or [0e].00  (bitmask.  bit2=FM)
-       ** audio proc: tag [02].01 or [05].00 (lower nibble indexes lut?)
+       ** tuner type:   tag [00].05 or [0a].01 (index into hauppauge_tuner)
+       ** tuner fmts:   tag [00].04 or [0a].00 (bitmask index into hauppauge_tuner_fmt)
+       ** radio:        tag [00].{last} or [0e].00  (bitmask.  bit2=FM)
+       ** audio proc:   tag [02].01 or [05].00 (mask with 0x7f)
+       ** decoder proc: tag [09].01)
 
        ** Fun info:
        ** model:      tag [00].07-08 or [06].00-01
@@ -273,20 +312,24 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
        ** # of inputs/outputs ???
        */
 
-       int i, j, len, done, beenhere, tag, tuner = 0, t_format = 0;
-       char *t_name = NULL, *t_fmt_name = NULL;
+       int i, j, len, done, beenhere, tag;
 
-       dprintk(1, "%s\n",__FUNCTION__);
-       tvee->revision = done = len = beenhere = 0;
-       for (i = 0; !done && i < 256; i += len) {
-               dprintk(2, "processing pos = %02x (%02x, %02x)\n",
-                       i, eeprom_data[i], eeprom_data[i + 1]);
+        int tuner1 = 0, t_format1 = 0;
+       char *t_name1 = NULL;
+        const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
 
+        int tuner2 = 0, t_format2 = 0;
+       char *t_name2 = NULL;
+        const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
+
+        memset(tvee, 0, sizeof(*tvee));
+       done = len = beenhere = 0;
+       for (i = 0; !done && i < 256; i += len) {
                if (eeprom_data[i] == 0x84) {
                        len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8);
-                       i+=3;
+                       i += 3;
                } else if ((eeprom_data[i] & 0xf0) == 0x70) {
-                       if ((eeprom_data[i] & 0x08)) {
+                       if (eeprom_data[i] & 0x08) {
                                /* verify checksum! */
                                done = 1;
                                break;
@@ -294,24 +337,30 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
                        len = eeprom_data[i] & 0x07;
                        ++i;
                } else {
-                       TVEEPROM_KERN_ERR("Encountered bad packet header [%02x]. "
+                       tveeprom_warn("Encountered bad packet header [%02x]. "
                                   "Corrupt or not a Hauppauge eeprom.\n", eeprom_data[i]);
                        return;
                }
 
-               dprintk(1, "%3d [%02x] ", len, eeprom_data[i]);
-               for(j = 1; j < len; j++) {
-                       dprintk(1, "%02x ", eeprom_data[i + j]);
-               }
-               dprintk(1, "\n");
+                if (debug) {
+                        tveeprom_info("Tag [%02x] + %d bytes:", eeprom_data[i], len - 1);
+                        for(j = 1; j < len; j++) {
+                                printk(" %02x", eeprom_data[i + j]);
+                        }
+                        printk("\n");
+                }
 
                /* process by tag */
                tag = eeprom_data[i];
                switch (tag) {
                case 0x00:
-                       tuner = eeprom_data[i+6];
-                       t_format = eeprom_data[i+5];
+                        /* tag: 'Comprehensive' */
+                       tuner1 = eeprom_data[i+6];
+                       t_format1 = eeprom_data[i+5];
                        tvee->has_radio = eeprom_data[i+len-1];
+                        /* old style tag, don't know how to detect
+                           IR presence, mark as unknown. */
+                       tvee->has_ir = 2;
                        tvee->model =
                                eeprom_data[i+8] +
                                (eeprom_data[i+9] << 8);
@@ -319,25 +368,43 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
                                (eeprom_data[i+11] << 8) +
                                (eeprom_data[i+12] << 16);
                        break;
+
                case 0x01:
+                        /* tag: 'SerialID' */
                        tvee->serial_number =
                                eeprom_data[i+6] +
                                (eeprom_data[i+7] << 8) +
                                (eeprom_data[i+8] << 16);
                        break;
+
                case 0x02:
-                       tvee->audio_processor = eeprom_data[i+2] & 0x0f;
+                        /* tag 'AudioInfo'
+                           Note mask with 0x7F, high bit used on some older models
+                           to indicate 4052 mux was removed in favor of using MSP
+                           inputs directly. */
+                       tvee->audio_processor = eeprom_data[i+2] & 0x7f;
                        break;
+
+                /* case 0x03: tag 'EEInfo' */
+
                case 0x04:
+                        /* tag 'SerialID2' */
                        tvee->serial_number =
                                eeprom_data[i+5] +
                                (eeprom_data[i+6] << 8) +
                                (eeprom_data[i+7] << 16);
                        break;
+
                case 0x05:
-                       tvee->audio_processor = eeprom_data[i+1] & 0x0f;
+                        /* tag 'Audio2'
+                           Note mask with 0x7F, high bit used on some older models
+                           to indicate 4052 mux was removed in favor of using MSP
+                           inputs directly. */
+                       tvee->audio_processor = eeprom_data[i+1] & 0x7f;
                        break;
+
                case 0x06:
+                        /* tag 'ModelRev' */
                        tvee->model =
                                eeprom_data[i+1] +
                                (eeprom_data[i+2] << 8);
@@ -345,27 +412,66 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
                                (eeprom_data[i+6] << 8) +
                                (eeprom_data[i+7] << 16);
                        break;
+
+               case 0x07:
+                        /* tag 'Details': according to Hauppauge not interesting
+                           on any PCI-era or later boards. */
+                       break;
+
+                /* there is no tag 0x08 defined */
+
+               case 0x09:
+                        /* tag 'Video' */
+                       tvee->decoder_processor = eeprom_data[i + 1];
+                       break;
+
                case 0x0a:
-                       if(beenhere == 0) {
-                               tuner = eeprom_data[i+2];
-                               t_format = eeprom_data[i+1];
+                        /* tag 'Tuner' */
+                       if (beenhere == 0) {
+                               tuner1 = eeprom_data[i+2];
+                               t_format1 = eeprom_data[i+1];
                                beenhere = 1;
-                               break;
                        } else {
-                               break;
-                       }
+                                /* a second (radio) tuner may be present */
+                               tuner2 = eeprom_data[i+2];
+                               t_format2 = eeprom_data[i+1];
+                                if (t_format2 == 0) {  /* not a TV tuner? */
+                                        tvee->has_radio = 1; /* must be radio */
+                                }
+                        }
+                       break;
+
+                case 0x0b:
+                        /* tag 'Inputs': according to Hauppauge this is specific
+                           to each driver family, so no good assumptions can be
+                           made. */
+                        break;
+
+                /* case 0x0c: tag 'Balun' */
+                /* case 0x0d: tag 'Teletext' */
+
                case 0x0e:
+                        /* tag: 'Radio' */
                        tvee->has_radio = eeprom_data[i+1];
                        break;
+
+                case 0x0f:
+                        /* tag 'IRInfo' */
+                        tvee->has_ir = eeprom_data[i+1];
+                        break;
+
+                /* case 0x10: tag 'VBIInfo' */
+                /* case 0x11: tag 'QCInfo' */
+                /* case 0x12: tag 'InfoBits' */
+
                default:
-                       dprintk(1, "Not sure what to do with tag [%02x]\n", tag);
+                       tveeprom_dbg("Not sure what to do with tag [%02x]\n", tag);
                        /* dump the rest of the packet? */
                }
-
        }
 
        if (!done) {
-               TVEEPROM_KERN_ERR("Ran out of data!\n");
+               tveeprom_warn("Ran out of data!\n");
                return;
        }
 
@@ -377,47 +483,72 @@ void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data
                tvee->rev_str[4] = 0;
        }
 
-        if (hasRadioTuner(tuner) && !tvee->has_radio) {
-           TVEEPROM_KERN_INFO("The eeprom says no radio is present, but the tuner type\n");
-           TVEEPROM_KERN_INFO("indicates otherwise. I will assume that radio is present.\n");
+        if (hasRadioTuner(tuner1) && !tvee->has_radio) {
+           tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
+           tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
             tvee->has_radio = 1;
         }
 
-       if (tuner < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
-               tvee->tuner_type = hauppauge_tuner[tuner].id;
-               t_name = hauppauge_tuner[tuner].name;
+       if (tuner1 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
+               tvee->tuner_type = hauppauge_tuner[tuner1].id;
+               t_name1 = hauppauge_tuner[tuner1].name;
        } else {
-               t_name = "<unknown>";
+               t_name1 = "unknown";
+       }
+
+       if (tuner2 < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) {
+               tvee->tuner2_type = hauppauge_tuner[tuner2].id;
+               t_name2 = hauppauge_tuner[tuner2].name;
+       } else {
+               t_name2 = "unknown";
        }
 
        tvee->tuner_formats = 0;
-       t_fmt_name = "<none>";
-       for (i = 0; i < 8; i++) {
-               if (t_format & (1<<i)) {
+       tvee->tuner2_formats = 0;
+       for (i = j = 0; i < 8; i++) {
+               if (t_format1 & (1 << i)) {
                        tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
-                       /* yuck */
-                       t_fmt_name = hauppauge_tuner_fmt[i].name;
+                       t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
                }
+                if (t_format2 & (1 << i)) {
+                        tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
+                        t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
+                }
        }
 
-
-       TVEEPROM_KERN_INFO("Hauppauge: model = %d, rev = %s, serial# = %d\n",
-                  tvee->model,
-                  tvee->rev_str,
-                  tvee->serial_number);
-       TVEEPROM_KERN_INFO("tuner = %s (idx = %d, type = %d)\n",
-                  t_name,
-                  tuner,
-                  tvee->tuner_type);
-       TVEEPROM_KERN_INFO("tuner fmt = %s (eeprom = 0x%02x, v4l2 = 0x%08x)\n",
-                  t_fmt_name,
-                  t_format,
-                  tvee->tuner_formats);
-
-       TVEEPROM_KERN_INFO("audio_processor = %s (type = %d)\n",
-                  STRM(sndtype,tvee->audio_processor),
+       tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
+                  tvee->model, tvee->rev_str, tvee->serial_number);
+       tveeprom_info("tuner model is %s (idx %d, type %d)\n",
+                  t_name1, tuner1, tvee->tuner_type);
+       tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+                  t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2], t_fmt_name1[3],
+                  t_fmt_name1[4], t_fmt_name1[5], t_fmt_name1[6], t_fmt_name1[7],
+                   t_format1);
+        if (tuner2) {
+                tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
+                           t_name2, tuner2, tvee->tuner2_type);
+        }
+        if (t_format2) {
+                tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+                           t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2], t_fmt_name2[3],
+                           t_fmt_name2[4], t_fmt_name2[5], t_fmt_name2[6], t_fmt_name2[7],
+                           t_format2);
+        }
+       tveeprom_info("audio processor is %s (idx %d)\n",
+                  STRM(audioIC, tvee->audio_processor),
                   tvee->audio_processor);
-
+        if (tvee->decoder_processor) {
+                tveeprom_info("decoder processor is %s (idx %d)\n",
+                           STRM(decoderIC, tvee->decoder_processor),
+                           tvee->decoder_processor);
+        }
+        if (tvee->has_ir == 2)
+                tveeprom_info("has %sradio\n",
+                                tvee->has_radio ? "" : "no ");
+        else
+                tveeprom_info("has %sradio, has %sIR remote\n",
+                                tvee->has_radio ? "" : "no ",
+                                tvee->has_ir ? "" : "no ");
 }
 EXPORT_SYMBOL(tveeprom_hauppauge_analog);
 
@@ -429,40 +560,31 @@ int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
        unsigned char buf;
        int err;
 
-       dprintk(1, "%s\n",__FUNCTION__);
        buf = 0;
-       if (1 != (err = i2c_master_send(c,&buf,1))) {
-               printk(KERN_INFO "tveeprom(%s): Huh, no eeprom present (err=%d)?\n",
-                      c->name,err);
+       if (1 != (err = i2c_master_send(c, &buf, 1))) {
+               tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
                return -1;
        }
-       if (len != (err = i2c_master_recv(c,eedata,len))) {
-               printk(KERN_WARNING "tveeprom(%s): i2c eeprom read error (err=%d)\n",
-                      c->name,err);
+       if (len != (err = i2c_master_recv(c, eedata, len))) {
+               tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
                return -1;
        }
+        if (debug) {
+                int i;
+
+                tveeprom_info("full 256-byte eeprom dump:\n");
+                for (i = 0; i < len; i++) {
+                        if (0 == (i % 16))
+                                tveeprom_info("%02x:", i);
+                        printk(" %02x", eedata[i]);
+                        if (15 == (i % 16))
+                                printk("\n");
+                }
+        }
        return 0;
 }
 EXPORT_SYMBOL(tveeprom_read);
 
-#if 0
-int tveeprom_dump(unsigned char *eedata, int len)
-{
-       int i;
-
-       dprintk(1, "%s\n",__FUNCTION__);
-       for (i = 0; i < len; i++) {
-               if (0 == (i % 16))
-                       printk(KERN_INFO "tveeprom: %02x:",i);
-               printk(" %02x",eedata[i]);
-               if (15 == (i % 16))
-                       printk("\n");
-       }
-       return 0;
-}
-EXPORT_SYMBOL(tveeprom_dump);
-#endif  /*  0  */
-
 /* ----------------------------------------------------------------------- */
 /* needed for ivtv.sf.net at the moment.  Should go away in the long       */
 /* run, just call the exported tveeprom_* directly, there is no point in   */
@@ -495,12 +617,13 @@ tveeprom_command(struct i2c_client *client,
                buf = kmalloc(256,GFP_KERNEL);
                memset(buf,0,256);
                tveeprom_read(client,buf,256);
-               tveeprom_hauppauge_analog(&eeprom,buf);
+               tveeprom_hauppauge_analog(client, &eeprom,buf);
                kfree(buf);
                eeprom_props[0] = eeprom.tuner_type;
                eeprom_props[1] = eeprom.tuner_formats;
                eeprom_props[2] = eeprom.model;
                eeprom_props[3] = eeprom.revision;
+               eeprom_props[4] = eeprom.has_radio;
                break;
        default:
                return -EINVAL;
@@ -515,8 +638,6 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
 {
        struct i2c_client *client;
 
-       dprintk(1,"%s: id 0x%x @ 0x%x\n",__FUNCTION__,
-              adapter->id, address << 1);
        client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
        if (NULL == client)
                return -ENOMEM;
@@ -533,7 +654,6 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
 static int
 tveeprom_attach_adapter (struct i2c_adapter *adapter)
 {
-       dprintk(1,"%s: id 0x%x\n",__FUNCTION__,adapter->id);
        if (adapter->id != I2C_HW_B_BT848)
                return 0;
        return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
index a43301a154af413dc2f5754beaa410ee3dfd14ca..d86e08ebddfc253506389050d3ef468dcbf3d532 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
  */
 
 #include <linux/module.h>
index 70ecbdb80277f58512342b81de6351333a5f71d6..59bb71381a1b19f18877348fee0561a8215efba3 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
  *
  *     Video for Linux Two
  *     Backward Compatibility Layer
@@ -604,9 +603,6 @@ v4l_compat_translate_ioctl(struct inode         *inode,
                        dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
                        break;
                }
-#if 0 /* FIXME */
-               pict->depth   = fmt2->fmt.pix.depth;
-#endif
                pict->palette = pixelformat_to_palette(
                        fmt2->fmt.pix.pixelformat);
                break;
@@ -707,13 +703,7 @@ v4l_compat_translate_ioctl(struct inode         *inode,
        }
        case VIDIOCSTUNER: /*  select a tuner input  */
        {
-#if 0 /* FIXME */
-               err = drv(inode, file, VIDIOC_S_INPUT, &i);
-               if (err < 0)
-                       dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
-#else
                err = 0;
-#endif
                break;
        }
        case VIDIOCGFREQ: /*  get frequency  */
@@ -852,12 +842,6 @@ v4l_compat_translate_ioctl(struct inode         *inode,
                err = 0;
                break;
        }
-#if 0
-       case VIDIOCGMBUF:
-               /* v4l2 drivers must implement that themself.  The
-                  mmap() differences can't be translated fully
-                  transparent, thus there is no point to try that */
-#endif
        case VIDIOCMCAPTURE: /*  capture a frame  */
        {
                struct video_mmap       *mm = arg;
index b5e0cf3448f498fb1d67d1cd03a415156cecf235..597b8db35a135c935b07e19d5ba08d816ec91946 100644 (file)
@@ -84,20 +84,6 @@ MODULE_LICENSE("GPL");
  *  Video Standard Operations (contributed by Michael Schimek)
  */
 
-#if 0 /* seems to have no users */
-/* This is the recommended method to deal with the framerate fields. More
-   sophisticated drivers will access the fields directly. */
-unsigned int
-v4l2_video_std_fps(struct v4l2_standard *vs)
-{
-       if (vs->frameperiod.numerator > 0)
-               return (((vs->frameperiod.denominator << 8) /
-                        vs->frameperiod.numerator) +
-                       (1 << 7)) / (1 << 8);
-       return 0;
-}
-EXPORT_SYMBOL(v4l2_video_std_fps);
-#endif
 
 /* Fill in the fields of a v4l2_standard structure according to the
    'id' and 'transmission' parameters.  Returns negative on error.  */
@@ -213,10 +199,6 @@ char *v4l2_ioctl_names[256] = {
        [_IOC_NR(VIDIOC_ENUM_FMT)]       = "VIDIOC_ENUM_FMT",
        [_IOC_NR(VIDIOC_G_FMT)]          = "VIDIOC_G_FMT",
        [_IOC_NR(VIDIOC_S_FMT)]          = "VIDIOC_S_FMT",
-#if 0
-       [_IOC_NR(VIDIOC_G_COMP)]         = "VIDIOC_G_COMP",
-       [_IOC_NR(VIDIOC_S_COMP)]         = "VIDIOC_S_COMP",
-#endif
        [_IOC_NR(VIDIOC_REQBUFS)]        = "VIDIOC_REQBUFS",
        [_IOC_NR(VIDIOC_QUERYBUF)]       = "VIDIOC_QUERYBUF",
        [_IOC_NR(VIDIOC_G_FBUF)]         = "VIDIOC_G_FBUF",
index 15f5bb4869638a78a1dcc94f1196d251d350e361..55f129e964eb6d91716c681ab845f892c4d1a45a 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: video-buf-dvb.c,v 1.7 2004/12/09 12:51:35 kraxel Exp $
  *
  * some helper function for simple DVB cards which simply DMA the
  * complete transport stream and let the computer sort everything else
index 5afdc785261036d9016a4e234a01e6377e16c520..574b8e36f3c611e54e4698db948b2dd04c9b8cb3 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: video-buf.c,v 1.18 2005/02/24 13:32:30 kraxel Exp $
  *
  * generic helper functions for video4linux capture buffers, to handle
  * memory management and PCI DMA.  Right now bttv + saa7134 use it.
@@ -268,10 +267,10 @@ int videobuf_dma_free(struct videobuf_dmabuf *dma)
                kfree(dma->pages);
                dma->pages = NULL;
        }
-       if (dma->vmalloc) {
-               vfree(dma->vmalloc);
-               dma->vmalloc = NULL;
-       }
+
+       vfree(dma->vmalloc);
+       dma->vmalloc = NULL;
+
        if (dma->bus_addr) {
                dma->bus_addr = 0;
        }
index ba838a42ec806c7e8fe1d55abb2ac1626585a28a..53adeb70f2cafb2f7a551ff5e121782f306df329 100644 (file)
@@ -650,7 +650,7 @@ jpg_fbuffer_free (struct file *file)
                                     off += PAGE_SIZE)
                                        ClearPageReserved(MAP_NR
                                                          (mem + off));
-                               kfree((void *) mem);
+                               kfree(mem);
                                fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
                                fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
                        }
index c33533155cc7242f9954dfd8a80ea5d4ae710625..07286816d7dfd4828df6aa879f17e02c864ac2d1 100644 (file)
@@ -820,11 +820,9 @@ void zoran_close(struct video_device* dev)
         msleep(100);                   /* Wait 1/10th of a second */
 
        /* free the allocated framebuffer */
-       if (ztv->fbuffer)
-               bfree( ztv->fbuffer, ZORAN_MAX_FBUFSIZE );
+       bfree(ztv->fbuffer, ZORAN_MAX_FBUFSIZE);
        ztv->fbuffer = 0;
-       if (ztv->overinfo.overlay)
-               kfree( ztv->overinfo.overlay );
+       kfree(ztv->overinfo.overlay);
        ztv->overinfo.overlay = 0;
 
 }
index 1588a59e3767a18a2a03fbf7bf1ba7a0d54b2bbb..550f29744812fe15c748f5c04670df0fcf11492b 100644 (file)
@@ -13,4 +13,13 @@ config MCP_SA11X0
        depends on ARCH_SA1100
        select MCP
 
+# Chip drivers
+config MCP_UCB1200
+       tristate "Support for UCB1200 / UCB1300"
+       depends on MCP
+
+config MCP_UCB1200_TS
+       tristate "Touchscreen interface support"
+       depends on MCP_UCB1200 && INPUT
+
 endmenu
index 98bdd6a421889c9d9d400c1c3e22e0c9a527e51c..adb29b5368a8deb7a75758c12df7a3577e6a0648 100644 (file)
@@ -4,3 +4,9 @@
 
 obj-$(CONFIG_MCP)              += mcp-core.o
 obj-$(CONFIG_MCP_SA11X0)       += mcp-sa11x0.o
+obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-core.o
+obj-$(CONFIG_MCP_UCB1200_TS)   += ucb1x00-ts.o
+
+ifeq ($(CONFIG_SA1100_ASSABET),y)
+obj-$(CONFIG_MCP_UCB1200)      += ucb1x00-assabet.o
+endif
diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c
new file mode 100644 (file)
index 0000000..e325fa7
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  linux/drivers/mfd/ucb1x00-assabet.c
+ *
+ *  Copyright (C) 2001-2003 Russell King, 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.
+ *
+ *  We handle the machine-specific bits of the UCB1x00 driver here.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+
+#include "ucb1x00.h"
+
+#define UCB1X00_ATTR(name,input)\
+static ssize_t name##_show(struct class_device *dev, char *buf)        \
+{                                                              \
+       struct ucb1x00 *ucb = classdev_to_ucb1x00(dev);         \
+       int val;                                                \
+       ucb1x00_adc_enable(ucb);                                \
+       val = ucb1x00_adc_read(ucb, input, UCB_NOSYNC);         \
+       ucb1x00_adc_disable(ucb);                               \
+       return sprintf(buf, "%d\n", val);                       \
+}                                                              \
+static CLASS_DEVICE_ATTR(name,0444,name##_show,NULL)
+
+UCB1X00_ATTR(vbatt, UCB_ADC_INP_AD1);
+UCB1X00_ATTR(vcharger, UCB_ADC_INP_AD0);
+UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2);
+
+static int ucb1x00_assabet_add(struct ucb1x00_dev *dev)
+{
+       class_device_create_file(&dev->ucb->cdev, &class_device_attr_vbatt);
+       class_device_create_file(&dev->ucb->cdev, &class_device_attr_vcharger);
+       class_device_create_file(&dev->ucb->cdev, &class_device_attr_batt_temp);
+       return 0;
+}
+
+static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev)
+{
+       class_device_remove_file(&dev->ucb->cdev, &class_device_attr_batt_temp);
+       class_device_remove_file(&dev->ucb->cdev, &class_device_attr_vcharger);
+       class_device_remove_file(&dev->ucb->cdev, &class_device_attr_vbatt);
+}
+
+static struct ucb1x00_driver ucb1x00_assabet_driver = {
+       .add    = ucb1x00_assabet_add,
+       .remove = ucb1x00_assabet_remove,
+};
+
+static int __init ucb1x00_assabet_init(void)
+{
+       return ucb1x00_register_driver(&ucb1x00_assabet_driver);
+}
+
+static void __exit ucb1x00_assabet_exit(void)
+{
+       ucb1x00_unregister_driver(&ucb1x00_assabet_driver);
+}
+
+module_init(ucb1x00_assabet_init);
+module_exit(ucb1x00_assabet_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
new file mode 100644 (file)
index 0000000..10f6ce1
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ *  linux/drivers/mfd/ucb1x00-core.c
+ *
+ *  Copyright (C) 2001 Russell King, 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.
+ *
+ *  The UCB1x00 core driver provides basic services for handling IO,
+ *  the ADC, interrupts, and accessing registers.  It is designed
+ *  such that everything goes through this layer, thereby providing
+ *  a consistent locking methodology, as well as allowing the drivers
+ *  to be used on other non-MCP-enabled hardware platforms.
+ *
+ *  Note that all locks are private to this file.  Nothing else may
+ *  touch them.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <asm/dma.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include "ucb1x00.h"
+
+static DECLARE_MUTEX(ucb1x00_sem);
+static LIST_HEAD(ucb1x00_drivers);
+static LIST_HEAD(ucb1x00_devices);
+
+/**
+ *     ucb1x00_io_set_dir - set IO direction
+ *     @ucb: UCB1x00 structure describing chip
+ *     @in:  bitfield of IO pins to be set as inputs
+ *     @out: bitfield of IO pins to be set as outputs
+ *
+ *     Set the IO direction of the ten general purpose IO pins on
+ *     the UCB1x00 chip.  The @in bitfield has priority over the
+ *     @out bitfield, in that if you specify a pin as both input
+ *     and output, it will end up as an input.
+ *
+ *     ucb1x00_enable must have been called to enable the comms
+ *     before using this function.
+ *
+ *     This function takes a spinlock, disabling interrupts.
+ */
+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int in, unsigned int out)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ucb->io_lock, flags);
+       ucb->io_dir |= out;
+       ucb->io_dir &= ~in;
+
+       ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+       spin_unlock_irqrestore(&ucb->io_lock, flags);
+}
+
+/**
+ *     ucb1x00_io_write - set or clear IO outputs
+ *     @ucb:   UCB1x00 structure describing chip
+ *     @set:   bitfield of IO pins to set to logic '1'
+ *     @clear: bitfield of IO pins to set to logic '0'
+ *
+ *     Set the IO output state of the specified IO pins.  The value
+ *     is retained if the pins are subsequently configured as inputs.
+ *     The @clear bitfield has priority over the @set bitfield -
+ *     outputs will be cleared.
+ *
+ *     ucb1x00_enable must have been called to enable the comms
+ *     before using this function.
+ *
+ *     This function takes a spinlock, disabling interrupts.
+ */
+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ucb->io_lock, flags);
+       ucb->io_out |= set;
+       ucb->io_out &= ~clear;
+
+       ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+       spin_unlock_irqrestore(&ucb->io_lock, flags);
+}
+
+/**
+ *     ucb1x00_io_read - read the current state of the IO pins
+ *     @ucb: UCB1x00 structure describing chip
+ *
+ *     Return a bitfield describing the logic state of the ten
+ *     general purpose IO pins.
+ *
+ *     ucb1x00_enable must have been called to enable the comms
+ *     before using this function.
+ *
+ *     This function does not take any semaphores or spinlocks.
+ */
+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
+{
+       return ucb1x00_reg_read(ucb, UCB_IO_DATA);
+}
+
+/*
+ * UCB1300 data sheet says we must:
+ *  1. enable ADC      => 5us (including reference startup time)
+ *  2. select input    => 51*tsibclk  => 4.3us
+ *  3. start conversion        => 102*tsibclk => 8.5us
+ * (tsibclk = 1/11981000)
+ * Period between SIB 128-bit frames = 10.7us
+ */
+
+/**
+ *     ucb1x00_adc_enable - enable the ADC converter
+ *     @ucb: UCB1x00 structure describing chip
+ *
+ *     Enable the ucb1x00 and ADC converter on the UCB1x00 for use.
+ *     Any code wishing to use the ADC converter must call this
+ *     function prior to using it.
+ *
+ *     This function takes the ADC semaphore to prevent two or more
+ *     concurrent uses, and therefore may sleep.  As a result, it
+ *     can only be called from process context, not interrupt
+ *     context.
+ *
+ *     You should release the ADC as soon as possible using
+ *     ucb1x00_adc_disable.
+ */
+void ucb1x00_adc_enable(struct ucb1x00 *ucb)
+{
+       down(&ucb->adc_sem);
+
+       ucb->adc_cr |= UCB_ADC_ENA;
+
+       ucb1x00_enable(ucb);
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
+}
+
+/**
+ *     ucb1x00_adc_read - read the specified ADC channel
+ *     @ucb: UCB1x00 structure describing chip
+ *     @adc_channel: ADC channel mask
+ *     @sync: wait for syncronisation pulse.
+ *
+ *     Start an ADC conversion and wait for the result.  Note that
+ *     synchronised ADC conversions (via the ADCSYNC pin) must wait
+ *     until the trigger is asserted and the conversion is finished.
+ *
+ *     This function currently spins waiting for the conversion to
+ *     complete (2 frames max without sync).
+ *
+ *     If called for a synchronised ADC conversion, it may sleep
+ *     with the ADC semaphore held.
+ */
+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
+{
+       unsigned int val;
+
+       if (sync)
+               adc_channel |= UCB_ADC_SYNC_ENA;
+
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel);
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr | adc_channel | UCB_ADC_START);
+
+       for (;;) {
+               val = ucb1x00_reg_read(ucb, UCB_ADC_DATA);
+               if (val & UCB_ADC_DAT_VAL)
+                       break;
+               /* yield to other processes */
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(1);
+       }
+
+       return UCB_ADC_DAT(val);
+}
+
+/**
+ *     ucb1x00_adc_disable - disable the ADC converter
+ *     @ucb: UCB1x00 structure describing chip
+ *
+ *     Disable the ADC converter and release the ADC semaphore.
+ */
+void ucb1x00_adc_disable(struct ucb1x00 *ucb)
+{
+       ucb->adc_cr &= ~UCB_ADC_ENA;
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
+       ucb1x00_disable(ucb);
+
+       up(&ucb->adc_sem);
+}
+
+/*
+ * UCB1x00 Interrupt handling.
+ *
+ * The UCB1x00 can generate interrupts when the SIBCLK is stopped.
+ * Since we need to read an internal register, we must re-enable
+ * SIBCLK to talk to the chip.  We leave the clock running until
+ * we have finished processing all interrupts from the chip.
+ */
+static irqreturn_t ucb1x00_irq(int irqnr, void *devid, struct pt_regs *regs)
+{
+       struct ucb1x00 *ucb = devid;
+       struct ucb1x00_irq *irq;
+       unsigned int isr, i;
+
+       ucb1x00_enable(ucb);
+       isr = ucb1x00_reg_read(ucb, UCB_IE_STATUS);
+       ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
+       ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+       for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
+               if (isr & 1 && irq->fn)
+                       irq->fn(i, irq->devid);
+       ucb1x00_disable(ucb);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ *     ucb1x00_hook_irq - hook a UCB1x00 interrupt
+ *     @ucb:   UCB1x00 structure describing chip
+ *     @idx:   interrupt index
+ *     @fn:    function to call when interrupt is triggered
+ *     @devid: device id to pass to interrupt handler
+ *
+ *     Hook the specified interrupt.  You can only register one handler
+ *     for each interrupt source.  The interrupt source is not enabled
+ *     by this function; use ucb1x00_enable_irq instead.
+ *
+ *     Interrupt handlers will be called with other interrupts enabled.
+ *
+ *     Returns zero on success, or one of the following errors:
+ *      -EINVAL if the interrupt index is invalid
+ *      -EBUSY if the interrupt has already been hooked
+ */
+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
+{
+       struct ucb1x00_irq *irq;
+       int ret = -EINVAL;
+
+       if (idx < 16) {
+               irq = ucb->irq_handler + idx;
+               ret = -EBUSY;
+
+               spin_lock_irq(&ucb->lock);
+               if (irq->fn == NULL) {
+                       irq->devid = devid;
+                       irq->fn = fn;
+                       ret = 0;
+               }
+               spin_unlock_irq(&ucb->lock);
+       }
+       return ret;
+}
+
+/**
+ *     ucb1x00_enable_irq - enable an UCB1x00 interrupt source
+ *     @ucb: UCB1x00 structure describing chip
+ *     @idx: interrupt index
+ *     @edges: interrupt edges to enable
+ *
+ *     Enable the specified interrupt to trigger on %UCB_RISING,
+ *     %UCB_FALLING or both edges.  The interrupt should have been
+ *     hooked by ucb1x00_hook_irq.
+ */
+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+{
+       unsigned long flags;
+
+       if (idx < 16) {
+               spin_lock_irqsave(&ucb->lock, flags);
+
+               ucb1x00_enable(ucb);
+               if (edges & UCB_RISING) {
+                       ucb->irq_ris_enbl |= 1 << idx;
+                       ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+               }
+               if (edges & UCB_FALLING) {
+                       ucb->irq_fal_enbl |= 1 << idx;
+                       ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+               }
+               ucb1x00_disable(ucb);
+               spin_unlock_irqrestore(&ucb->lock, flags);
+       }
+}
+
+/**
+ *     ucb1x00_disable_irq - disable an UCB1x00 interrupt source
+ *     @ucb: UCB1x00 structure describing chip
+ *     @edges: interrupt edges to disable
+ *
+ *     Disable the specified interrupt triggering on the specified
+ *     (%UCB_RISING, %UCB_FALLING or both) edges.
+ */
+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
+{
+       unsigned long flags;
+
+       if (idx < 16) {
+               spin_lock_irqsave(&ucb->lock, flags);
+
+               ucb1x00_enable(ucb);
+               if (edges & UCB_RISING) {
+                       ucb->irq_ris_enbl &= ~(1 << idx);
+                       ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+               }
+               if (edges & UCB_FALLING) {
+                       ucb->irq_fal_enbl &= ~(1 << idx);
+                       ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+               }
+               ucb1x00_disable(ucb);
+               spin_unlock_irqrestore(&ucb->lock, flags);
+       }
+}
+
+/**
+ *     ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
+ *     @ucb: UCB1x00 structure describing chip
+ *     @idx: interrupt index
+ *     @devid: device id.
+ *
+ *     Disable the interrupt source and remove the handler.  devid must
+ *     match the devid passed when hooking the interrupt.
+ *
+ *     Returns zero on success, or one of the following errors:
+ *      -EINVAL if the interrupt index is invalid
+ *      -ENOENT if devid does not match
+ */
+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
+{
+       struct ucb1x00_irq *irq;
+       int ret;
+
+       if (idx >= 16)
+               goto bad;
+
+       irq = ucb->irq_handler + idx;
+       ret = -ENOENT;
+
+       spin_lock_irq(&ucb->lock);
+       if (irq->devid == devid) {
+               ucb->irq_ris_enbl &= ~(1 << idx);
+               ucb->irq_fal_enbl &= ~(1 << idx);
+
+               ucb1x00_enable(ucb);
+               ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
+               ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
+               ucb1x00_disable(ucb);
+
+               irq->fn = NULL;
+               irq->devid = NULL;
+               ret = 0;
+       }
+       spin_unlock_irq(&ucb->lock);
+       return ret;
+
+bad:
+       printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx);
+       return -EINVAL;
+}
+
+static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
+{
+       struct ucb1x00_dev *dev;
+       int ret = -ENOMEM;
+
+       dev = kmalloc(sizeof(struct ucb1x00_dev), GFP_KERNEL);
+       if (dev) {
+               dev->ucb = ucb;
+               dev->drv = drv;
+
+               ret = drv->add(dev);
+
+               if (ret == 0) {
+                       list_add(&dev->dev_node, &ucb->devs);
+                       list_add(&dev->drv_node, &drv->devs);
+               } else {
+                       kfree(dev);
+               }
+       }
+       return ret;
+}
+
+static void ucb1x00_remove_dev(struct ucb1x00_dev *dev)
+{
+       dev->drv->remove(dev);
+       list_del(&dev->dev_node);
+       list_del(&dev->drv_node);
+       kfree(dev);
+}
+
+/*
+ * Try to probe our interrupt, rather than relying on lots of
+ * hard-coded machine dependencies.  For reference, the expected
+ * IRQ mappings are:
+ *
+ *     Machine         Default IRQ
+ *     adsbitsy        IRQ_GPCIN4
+ *     cerf            IRQ_GPIO_UCB1200_IRQ
+ *     flexanet        IRQ_GPIO_GUI
+ *     freebird        IRQ_GPIO_FREEBIRD_UCB1300_IRQ
+ *     graphicsclient  ADS_EXT_IRQ(8)
+ *     graphicsmaster  ADS_EXT_IRQ(8)
+ *     lart            LART_IRQ_UCB1200
+ *     omnimeter       IRQ_GPIO23
+ *     pfs168          IRQ_GPIO_UCB1300_IRQ
+ *     simpad          IRQ_GPIO_UCB1300_IRQ
+ *     shannon         SHANNON_IRQ_GPIO_IRQ_CODEC
+ *     yopy            IRQ_GPIO_UCB1200_IRQ
+ */
+static int ucb1x00_detect_irq(struct ucb1x00 *ucb)
+{
+       unsigned long mask;
+
+       mask = probe_irq_on();
+       if (!mask)
+               return NO_IRQ;
+
+       /*
+        * Enable the ADC interrupt.
+        */
+       ucb1x00_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC);
+       ucb1x00_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC);
+       ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+       ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+       /*
+        * Cause an ADC interrupt.
+        */
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA);
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START);
+
+       /*
+        * Wait for the conversion to complete.
+        */
+       while ((ucb1x00_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VAL) == 0);
+       ucb1x00_reg_write(ucb, UCB_ADC_CR, 0);
+
+       /*
+        * Disable and clear interrupt.
+        */
+       ucb1x00_reg_write(ucb, UCB_IE_RIS, 0);
+       ucb1x00_reg_write(ucb, UCB_IE_FAL, 0);
+       ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0xffff);
+       ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
+
+       /*
+        * Read triggered interrupt.
+        */
+       return probe_irq_off(mask);
+}
+
+static int ucb1x00_probe(struct mcp *mcp)
+{
+       struct ucb1x00 *ucb;
+       struct ucb1x00_driver *drv;
+       unsigned int id;
+       int ret = -ENODEV;
+
+       mcp_enable(mcp);
+       id = mcp_reg_read(mcp, UCB_ID);
+
+       if (id != UCB_ID_1200 && id != UCB_ID_1300) {
+               printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
+               goto err_disable;
+       }
+
+       ucb = kmalloc(sizeof(struct ucb1x00), GFP_KERNEL);
+       ret = -ENOMEM;
+       if (!ucb)
+               goto err_disable;
+
+       memset(ucb, 0, sizeof(struct ucb1x00));
+
+       ucb->cdev.class = &ucb1x00_class;
+       ucb->cdev.dev = &mcp->attached_device;
+       strlcpy(ucb->cdev.class_id, "ucb1x00", sizeof(ucb->cdev.class_id));
+
+       spin_lock_init(&ucb->lock);
+       spin_lock_init(&ucb->io_lock);
+       sema_init(&ucb->adc_sem, 1);
+
+       ucb->id  = id;
+       ucb->mcp = mcp;
+       ucb->irq = ucb1x00_detect_irq(ucb);
+       if (ucb->irq == NO_IRQ) {
+               printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
+               ret = -ENODEV;
+               goto err_free;
+       }
+
+       ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb);
+       if (ret) {
+               printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
+                       ucb->irq, ret);
+               goto err_free;
+       }
+
+       set_irq_type(ucb->irq, IRQT_RISING);
+       mcp_set_drvdata(mcp, ucb);
+
+       ret = class_device_register(&ucb->cdev);
+       if (ret)
+               goto err_irq;
+
+       INIT_LIST_HEAD(&ucb->devs);
+       down(&ucb1x00_sem);
+       list_add(&ucb->node, &ucb1x00_devices);
+       list_for_each_entry(drv, &ucb1x00_drivers, node) {
+               ucb1x00_add_dev(ucb, drv);
+       }
+       up(&ucb1x00_sem);
+       goto out;
+
+ err_irq:
+       free_irq(ucb->irq, ucb);
+ err_free:
+       kfree(ucb);
+ err_disable:
+       mcp_disable(mcp);
+ out:
+       return ret;
+}
+
+static void ucb1x00_remove(struct mcp *mcp)
+{
+       struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+       struct list_head *l, *n;
+
+       down(&ucb1x00_sem);
+       list_del(&ucb->node);
+       list_for_each_safe(l, n, &ucb->devs) {
+               struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node);
+               ucb1x00_remove_dev(dev);
+       }
+       up(&ucb1x00_sem);
+
+       free_irq(ucb->irq, ucb);
+       class_device_unregister(&ucb->cdev);
+}
+
+static void ucb1x00_release(struct class_device *dev)
+{
+       struct ucb1x00 *ucb = classdev_to_ucb1x00(dev);
+       kfree(ucb);
+}
+
+static struct class ucb1x00_class = {
+       .name           = "ucb1x00",
+       .release        = ucb1x00_release,
+};
+
+int ucb1x00_register_driver(struct ucb1x00_driver *drv)
+{
+       struct ucb1x00 *ucb;
+
+       INIT_LIST_HEAD(&drv->devs);
+       down(&ucb1x00_sem);
+       list_add(&drv->node, &ucb1x00_drivers);
+       list_for_each_entry(ucb, &ucb1x00_devices, node) {
+               ucb1x00_add_dev(ucb, drv);
+       }
+       up(&ucb1x00_sem);
+       return 0;
+}
+
+void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
+{
+       struct list_head *n, *l;
+
+       down(&ucb1x00_sem);
+       list_del(&drv->node);
+       list_for_each_safe(l, n, &drv->devs) {
+               struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node);
+               ucb1x00_remove_dev(dev);
+       }
+       up(&ucb1x00_sem);
+}
+
+static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
+{
+       struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+       struct ucb1x00_dev *dev;
+
+       down(&ucb1x00_sem);
+       list_for_each_entry(dev, &ucb->devs, dev_node) {
+               if (dev->drv->suspend)
+                       dev->drv->suspend(dev, state);
+       }
+       up(&ucb1x00_sem);
+       return 0;
+}
+
+static int ucb1x00_resume(struct mcp *mcp)
+{
+       struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
+       struct ucb1x00_dev *dev;
+
+       down(&ucb1x00_sem);
+       list_for_each_entry(dev, &ucb->devs, dev_node) {
+               if (dev->drv->resume)
+                       dev->drv->resume(dev);
+       }
+       up(&ucb1x00_sem);
+       return 0;
+}
+
+static struct mcp_driver ucb1x00_driver = {
+       .drv            = {
+               .name   = "ucb1x00",
+       },
+       .probe          = ucb1x00_probe,
+       .remove         = ucb1x00_remove,
+       .suspend        = ucb1x00_suspend,
+       .resume         = ucb1x00_resume,
+};
+
+static int __init ucb1x00_init(void)
+{
+       int ret = class_register(&ucb1x00_class);
+       if (ret == 0) {
+               ret = mcp_driver_register(&ucb1x00_driver);
+               if (ret)
+                       class_unregister(&ucb1x00_class);
+       }
+       return ret;
+}
+
+static void __exit ucb1x00_exit(void)
+{
+       mcp_driver_unregister(&ucb1x00_driver);
+       class_unregister(&ucb1x00_class);
+}
+
+module_init(ucb1x00_init);
+module_exit(ucb1x00_exit);
+
+EXPORT_SYMBOL(ucb1x00_class);
+
+EXPORT_SYMBOL(ucb1x00_io_set_dir);
+EXPORT_SYMBOL(ucb1x00_io_write);
+EXPORT_SYMBOL(ucb1x00_io_read);
+
+EXPORT_SYMBOL(ucb1x00_adc_enable);
+EXPORT_SYMBOL(ucb1x00_adc_read);
+EXPORT_SYMBOL(ucb1x00_adc_disable);
+
+EXPORT_SYMBOL(ucb1x00_hook_irq);
+EXPORT_SYMBOL(ucb1x00_free_irq);
+EXPORT_SYMBOL(ucb1x00_enable_irq);
+EXPORT_SYMBOL(ucb1x00_disable_irq);
+
+EXPORT_SYMBOL(ucb1x00_register_driver);
+EXPORT_SYMBOL(ucb1x00_unregister_driver);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("UCB1x00 core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
new file mode 100644 (file)
index 0000000..a851d65
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ *  Touchscreen driver for UCB1x00-based touchscreens
+ *
+ *  Copyright (C) 2001 Russell King, All Rights Reserved.
+ *  Copyright (C) 2005 Pavel Machek
+ *
+ * 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.
+ *
+ * 21-Jan-2002 <jco@ict.es> :
+ *
+ * Added support for synchronous A/D mode. This mode is useful to
+ * avoid noise induced in the touchpanel by the LCD, provided that
+ * the UCB1x00 has a valid LCD sync signal routed to its ADCSYNC pin.
+ * It is important to note that the signal connected to the ADCSYNC
+ * pin should provide pulses even when the LCD is blanked, otherwise
+ * a pen touch needed to unblank the LCD will never be read.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+
+#include <asm/dma.h>
+#include <asm/semaphore.h>
+
+#include "ucb1x00.h"
+
+
+struct ucb1x00_ts {
+       struct input_dev        idev;
+       struct ucb1x00          *ucb;
+
+       wait_queue_head_t       irq_wait;
+       struct task_struct      *rtask;
+       u16                     x_res;
+       u16                     y_res;
+
+       int                     restart:1;
+       int                     adcsync:1;
+};
+
+static int adcsync;
+
+static inline void ucb1x00_ts_evt_add(struct ucb1x00_ts *ts, u16 pressure, u16 x, u16 y)
+{
+       input_report_abs(&ts->idev, ABS_X, x);
+       input_report_abs(&ts->idev, ABS_Y, y);
+       input_report_abs(&ts->idev, ABS_PRESSURE, pressure);
+       input_sync(&ts->idev);
+}
+
+static inline void ucb1x00_ts_event_release(struct ucb1x00_ts *ts)
+{
+       input_report_abs(&ts->idev, ABS_PRESSURE, 0);
+       input_sync(&ts->idev);
+}
+
+/*
+ * Switch to interrupt mode.
+ */
+static inline void ucb1x00_ts_mode_int(struct ucb1x00_ts *ts)
+{
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+                       UCB_TS_CR_MODE_INT);
+}
+
+/*
+ * Switch to pressure mode, and read pressure.  We don't need to wait
+ * here, since both plates are being driven.
+ */
+static inline unsigned int ucb1x00_ts_read_pressure(struct ucb1x00_ts *ts)
+{
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+
+       return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+}
+
+/*
+ * Switch to X position mode and measure Y plate.  We switch the plate
+ * configuration in pressure mode, then switch to position mode.  This
+ * gives a faster response time.  Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1x00_ts_read_xpos(struct ucb1x00_ts *ts)
+{
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+       udelay(55);
+
+       return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPY, ts->adcsync);
+}
+
+/*
+ * Switch to Y position mode and measure X plate.  We switch the plate
+ * configuration in pressure mode, then switch to position mode.  This
+ * gives a faster response time.  Even so, we need to wait about 55us
+ * for things to stabilise.
+ */
+static inline unsigned int ucb1x00_ts_read_ypos(struct ucb1x00_ts *ts)
+{
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA);
+
+       udelay(55);
+
+       return ucb1x00_adc_read(ts->ucb, UCB_ADC_INP_TSPX, ts->adcsync);
+}
+
+/*
+ * Switch to X plate resistance mode.  Set MX to ground, PX to
+ * supply.  Measure current.
+ */
+static inline unsigned int ucb1x00_ts_read_xres(struct ucb1x00_ts *ts)
+{
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
+}
+
+/*
+ * Switch to Y plate resistance mode.  Set MY to ground, PY to
+ * supply.  Measure current.
+ */
+static inline unsigned int ucb1x00_ts_read_yres(struct ucb1x00_ts *ts)
+{
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR,
+                       UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW |
+                       UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA);
+       return ucb1x00_adc_read(ts->ucb, 0, ts->adcsync);
+}
+
+/*
+ * This is a RT kernel thread that handles the ADC accesses
+ * (mainly so we can use semaphores in the UCB1200 core code
+ * to serialise accesses to the ADC).
+ */
+static int ucb1x00_thread(void *_ts)
+{
+       struct ucb1x00_ts *ts = _ts;
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+       int valid;
+
+       /*
+        * We could run as a real-time thread.  However, thus far
+        * this doesn't seem to be necessary.
+        */
+//     tsk->policy = SCHED_FIFO;
+//     tsk->rt_priority = 1;
+
+       valid = 0;
+
+       add_wait_queue(&ts->irq_wait, &wait);
+       while (!kthread_should_stop()) {
+               unsigned int x, y, p, val;
+               signed long timeout;
+
+               ts->restart = 0;
+
+               ucb1x00_adc_enable(ts->ucb);
+
+               x = ucb1x00_ts_read_xpos(ts);
+               y = ucb1x00_ts_read_ypos(ts);
+               p = ucb1x00_ts_read_pressure(ts);
+
+               /*
+                * Switch back to interrupt mode.
+                */
+               ucb1x00_ts_mode_int(ts);
+               ucb1x00_adc_disable(ts->ucb);
+
+               msleep(10);
+
+               ucb1x00_enable(ts->ucb);
+               val = ucb1x00_reg_read(ts->ucb, UCB_TS_CR);
+
+               if (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)) {
+                       set_task_state(tsk, TASK_INTERRUPTIBLE);
+
+                       ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+                       ucb1x00_disable(ts->ucb);
+
+                       /*
+                        * If we spat out a valid sample set last time,
+                        * spit out a "pen off" sample here.
+                        */
+                       if (valid) {
+                               ucb1x00_ts_event_release(ts);
+                               valid = 0;
+                       }
+
+                       timeout = MAX_SCHEDULE_TIMEOUT;
+               } else {
+                       ucb1x00_disable(ts->ucb);
+
+                       /*
+                        * Filtering is policy.  Policy belongs in user
+                        * space.  We therefore leave it to user space
+                        * to do any filtering they please.
+                        */
+                       if (!ts->restart) {
+                               ucb1x00_ts_evt_add(ts, p, x, y);
+                               valid = 1;
+                       }
+
+                       set_task_state(tsk, TASK_INTERRUPTIBLE);
+                       timeout = HZ / 100;
+               }
+
+               try_to_freeze();
+
+               schedule_timeout(timeout);
+       }
+
+       remove_wait_queue(&ts->irq_wait, &wait);
+
+       ts->rtask = NULL;
+       return 0;
+}
+
+/*
+ * We only detect touch screen _touches_ with this interrupt
+ * handler, and even then we just schedule our task.
+ */
+static void ucb1x00_ts_irq(int idx, void *id)
+{
+       struct ucb1x00_ts *ts = id;
+       ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
+       wake_up(&ts->irq_wait);
+}
+
+static int ucb1x00_ts_open(struct input_dev *idev)
+{
+       struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
+       int ret = 0;
+
+       BUG_ON(ts->rtask);
+
+       init_waitqueue_head(&ts->irq_wait);
+       ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
+       if (ret < 0)
+               goto out;
+
+       /*
+        * If we do this at all, we should allow the user to
+        * measure and read the X and Y resistance at any time.
+        */
+       ucb1x00_adc_enable(ts->ucb);
+       ts->x_res = ucb1x00_ts_read_xres(ts);
+       ts->y_res = ucb1x00_ts_read_yres(ts);
+       ucb1x00_adc_disable(ts->ucb);
+
+       ts->rtask = kthread_run(ucb1x00_thread, ts, "ktsd");
+       if (!IS_ERR(ts->rtask)) {
+               ret = 0;
+       } else {
+               ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+               ts->rtask = NULL;
+               ret = -EFAULT;
+       }
+
+ out:
+       return ret;
+}
+
+/*
+ * Release touchscreen resources.  Disable IRQs.
+ */
+static void ucb1x00_ts_close(struct input_dev *idev)
+{
+       struct ucb1x00_ts *ts = (struct ucb1x00_ts *)idev;
+
+       if (ts->rtask)
+               kthread_stop(ts->rtask);
+
+       ucb1x00_enable(ts->ucb);
+       ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
+       ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
+       ucb1x00_disable(ts->ucb);
+}
+
+#ifdef CONFIG_PM
+static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
+{
+       struct ucb1x00_ts *ts = dev->priv;
+
+       if (ts->rtask != NULL) {
+               /*
+                * Restart the TS thread to ensure the
+                * TS interrupt mode is set up again
+                * after sleep.
+                */
+               ts->restart = 1;
+               wake_up(&ts->irq_wait);
+       }
+       return 0;
+}
+#else
+#define ucb1x00_ts_resume NULL
+#endif
+
+
+/*
+ * Initialisation.
+ */
+static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
+{
+       struct ucb1x00_ts *ts;
+
+       ts = kmalloc(sizeof(struct ucb1x00_ts), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       memset(ts, 0, sizeof(struct ucb1x00_ts));
+
+       ts->ucb = dev->ucb;
+       ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
+
+       ts->idev.name       = "Touchscreen panel";
+       ts->idev.id.product = ts->ucb->id;
+       ts->idev.open       = ucb1x00_ts_open;
+       ts->idev.close      = ucb1x00_ts_close;
+
+       __set_bit(EV_ABS, ts->idev.evbit);
+       __set_bit(ABS_X, ts->idev.absbit);
+       __set_bit(ABS_Y, ts->idev.absbit);
+       __set_bit(ABS_PRESSURE, ts->idev.absbit);
+
+       input_register_device(&ts->idev);
+
+       dev->priv = ts;
+
+       return 0;
+}
+
+static void ucb1x00_ts_remove(struct ucb1x00_dev *dev)
+{
+       struct ucb1x00_ts *ts = dev->priv;
+       input_unregister_device(&ts->idev);
+       kfree(ts);
+}
+
+static struct ucb1x00_driver ucb1x00_ts_driver = {
+       .add            = ucb1x00_ts_add,
+       .remove         = ucb1x00_ts_remove,
+       .resume         = ucb1x00_ts_resume,
+};
+
+static int __init ucb1x00_ts_init(void)
+{
+       return ucb1x00_register_driver(&ucb1x00_ts_driver);
+}
+
+static void __exit ucb1x00_ts_exit(void)
+{
+       ucb1x00_unregister_driver(&ucb1x00_ts_driver);
+}
+
+module_param(adcsync, int, 0444);
+module_init(ucb1x00_ts_init);
+module_exit(ucb1x00_ts_exit);
+
+MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
+MODULE_DESCRIPTION("UCB1x00 touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ucb1x00.h b/drivers/mfd/ucb1x00.h
new file mode 100644 (file)
index 0000000..6b63264
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ *  linux/drivers/mfd/ucb1x00.h
+ *
+ *  Copyright (C) 2001 Russell King, 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.
+ */
+#ifndef UCB1200_H
+#define UCB1200_H
+
+#define UCB_IO_DATA    0x00
+#define UCB_IO_DIR     0x01
+
+#define UCB_IO_0               (1 << 0)
+#define UCB_IO_1               (1 << 1)
+#define UCB_IO_2               (1 << 2)
+#define UCB_IO_3               (1 << 3)
+#define UCB_IO_4               (1 << 4)
+#define UCB_IO_5               (1 << 5)
+#define UCB_IO_6               (1 << 6)
+#define UCB_IO_7               (1 << 7)
+#define UCB_IO_8               (1 << 8)
+#define UCB_IO_9               (1 << 9)
+
+#define UCB_IE_RIS     0x02
+#define UCB_IE_FAL     0x03
+#define UCB_IE_STATUS  0x04
+#define UCB_IE_CLEAR   0x04
+#define UCB_IE_ADC             (1 << 11)
+#define UCB_IE_TSPX            (1 << 12)
+#define UCB_IE_TSMX            (1 << 13)
+#define UCB_IE_TCLIP           (1 << 14)
+#define UCB_IE_ACLIP           (1 << 15)
+
+#define UCB_IRQ_TSPX           12
+
+#define UCB_TC_A       0x05
+#define UCB_TC_A_LOOP          (1 << 7)        /* UCB1200 */
+#define UCB_TC_A_AMPL          (1 << 7)        /* UCB1300 */
+
+#define UCB_TC_B       0x06
+#define UCB_TC_B_VOICE_ENA     (1 << 3)
+#define UCB_TC_B_CLIP          (1 << 4)
+#define UCB_TC_B_ATT           (1 << 6)
+#define UCB_TC_B_SIDE_ENA      (1 << 11)
+#define UCB_TC_B_MUTE          (1 << 13)
+#define UCB_TC_B_IN_ENA                (1 << 14)
+#define UCB_TC_B_OUT_ENA       (1 << 15)
+
+#define UCB_AC_A       0x07
+#define UCB_AC_B       0x08
+#define UCB_AC_B_LOOP          (1 << 8)
+#define UCB_AC_B_MUTE          (1 << 13)
+#define UCB_AC_B_IN_ENA                (1 << 14)
+#define UCB_AC_B_OUT_ENA       (1 << 15)
+
+#define UCB_TS_CR      0x09
+#define UCB_TS_CR_TSMX_POW     (1 << 0)
+#define UCB_TS_CR_TSPX_POW     (1 << 1)
+#define UCB_TS_CR_TSMY_POW     (1 << 2)
+#define UCB_TS_CR_TSPY_POW     (1 << 3)
+#define UCB_TS_CR_TSMX_GND     (1 << 4)
+#define UCB_TS_CR_TSPX_GND     (1 << 5)
+#define UCB_TS_CR_TSMY_GND     (1 << 6)
+#define UCB_TS_CR_TSPY_GND     (1 << 7)
+#define UCB_TS_CR_MODE_INT     (0 << 8)
+#define UCB_TS_CR_MODE_PRES    (1 << 8)
+#define UCB_TS_CR_MODE_POS     (2 << 8)
+#define UCB_TS_CR_BIAS_ENA     (1 << 11)
+#define UCB_TS_CR_TSPX_LOW     (1 << 12)
+#define UCB_TS_CR_TSMX_LOW     (1 << 13)
+
+#define UCB_ADC_CR     0x0a
+#define UCB_ADC_SYNC_ENA       (1 << 0)
+#define UCB_ADC_VREFBYP_CON    (1 << 1)
+#define UCB_ADC_INP_TSPX       (0 << 2)
+#define UCB_ADC_INP_TSMX       (1 << 2)
+#define UCB_ADC_INP_TSPY       (2 << 2)
+#define UCB_ADC_INP_TSMY       (3 << 2)
+#define UCB_ADC_INP_AD0                (4 << 2)
+#define UCB_ADC_INP_AD1                (5 << 2)
+#define UCB_ADC_INP_AD2                (6 << 2)
+#define UCB_ADC_INP_AD3                (7 << 2)
+#define UCB_ADC_EXT_REF                (1 << 5)
+#define UCB_ADC_START          (1 << 7)
+#define UCB_ADC_ENA            (1 << 15)
+
+#define UCB_ADC_DATA   0x0b
+#define UCB_ADC_DAT_VAL                (1 << 15)
+#define UCB_ADC_DAT(x)         (((x) & 0x7fe0) >> 5)
+
+#define UCB_ID         0x0c
+#define UCB_ID_1200            0x1004
+#define UCB_ID_1300            0x1005
+
+#define UCB_MODE       0x0d
+#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
+#define UCB_MODE_AUD_OFF_CAN   (1 << 13)
+
+#include "mcp.h"
+
+struct ucb1x00_irq {
+       void *devid;
+       void (*fn)(int, void *);
+};
+
+extern struct class ucb1x00_class;
+
+struct ucb1x00 {
+       spinlock_t              lock;
+       struct mcp              *mcp;
+       unsigned int            irq;
+       struct semaphore        adc_sem;
+       spinlock_t              io_lock;
+       u16                     id;
+       u16                     io_dir;
+       u16                     io_out;
+       u16                     adc_cr;
+       u16                     irq_fal_enbl;
+       u16                     irq_ris_enbl;
+       struct ucb1x00_irq      irq_handler[16];
+       struct class_device     cdev;
+       struct list_head        node;
+       struct list_head        devs;
+};
+
+struct ucb1x00_driver;
+
+struct ucb1x00_dev {
+       struct list_head        dev_node;
+       struct list_head        drv_node;
+       struct ucb1x00          *ucb;
+       struct ucb1x00_driver   *drv;
+       void                    *priv;
+};
+
+struct ucb1x00_driver {
+       struct list_head        node;
+       struct list_head        devs;
+       int     (*add)(struct ucb1x00_dev *dev);
+       void    (*remove)(struct ucb1x00_dev *dev);
+       int     (*suspend)(struct ucb1x00_dev *dev, pm_message_t state);
+       int     (*resume)(struct ucb1x00_dev *dev);
+};
+
+#define classdev_to_ucb1x00(cd)        container_of(cd, struct ucb1x00, cdev)
+
+int ucb1x00_register_driver(struct ucb1x00_driver *);
+void ucb1x00_unregister_driver(struct ucb1x00_driver *);
+
+/**
+ *     ucb1x00_clkrate - return the UCB1x00 SIB clock rate
+ *     @ucb: UCB1x00 structure describing chip
+ *
+ *     Return the SIB clock rate in Hz.
+ */
+static inline unsigned int ucb1x00_clkrate(struct ucb1x00 *ucb)
+{
+       return mcp_get_sclk_rate(ucb->mcp);
+}
+
+/**
+ *     ucb1x00_enable - enable the UCB1x00 SIB clock
+ *     @ucb: UCB1x00 structure describing chip
+ *
+ *     Enable the SIB clock.  This can be called multiple times.
+ */
+static inline void ucb1x00_enable(struct ucb1x00 *ucb)
+{
+       mcp_enable(ucb->mcp);
+}
+
+/**
+ *     ucb1x00_disable - disable the UCB1x00 SIB clock
+ *     @ucb: UCB1x00 structure describing chip
+ *
+ *     Disable the SIB clock.  The SIB clock will only be disabled
+ *     when the number of ucb1x00_enable calls match the number of
+ *     ucb1x00_disable calls.
+ */
+static inline void ucb1x00_disable(struct ucb1x00 *ucb)
+{
+       mcp_disable(ucb->mcp);
+}
+
+/**
+ *     ucb1x00_reg_write - write a UCB1x00 register
+ *     @ucb: UCB1x00 structure describing chip
+ *     @reg: UCB1x00 4-bit register index to write
+ *     @val: UCB1x00 16-bit value to write
+ *
+ *     Write the UCB1x00 register @reg with value @val.  The SIB
+ *     clock must be running for this function to return.
+ */
+static inline void ucb1x00_reg_write(struct ucb1x00 *ucb, unsigned int reg, unsigned int val)
+{
+       mcp_reg_write(ucb->mcp, reg, val);
+}
+
+/**
+ *     ucb1x00_reg_read - read a UCB1x00 register
+ *     @ucb: UCB1x00 structure describing chip
+ *     @reg: UCB1x00 4-bit register index to write
+ *
+ *     Read the UCB1x00 register @reg and return its value.  The SIB
+ *     clock must be running for this function to return.
+ */
+static inline unsigned int ucb1x00_reg_read(struct ucb1x00 *ucb, unsigned int reg)
+{
+       return mcp_reg_read(ucb->mcp, reg);
+}
+/**
+ *     ucb1x00_set_audio_divisor - 
+ *     @ucb: UCB1x00 structure describing chip
+ *     @div: SIB clock divisor
+ */
+static inline void ucb1x00_set_audio_divisor(struct ucb1x00 *ucb, unsigned int div)
+{
+       mcp_set_audio_divisor(ucb->mcp, div);
+}
+
+/**
+ *     ucb1x00_set_telecom_divisor -
+ *     @ucb: UCB1x00 structure describing chip
+ *     @div: SIB clock divisor
+ */
+static inline void ucb1x00_set_telecom_divisor(struct ucb1x00 *ucb, unsigned int div)
+{
+       mcp_set_telecom_divisor(ucb->mcp, div);
+}
+
+void ucb1x00_io_set_dir(struct ucb1x00 *ucb, unsigned int, unsigned int);
+void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int, unsigned int);
+unsigned int ucb1x00_io_read(struct ucb1x00 *ucb);
+
+#define UCB_NOSYNC     (0)
+#define UCB_SYNC       (1)
+
+unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
+void ucb1x00_adc_enable(struct ucb1x00 *ucb);
+void ucb1x00_adc_disable(struct ucb1x00 *ucb);
+
+/*
+ * Which edges of the IRQ do you want to control today?
+ */
+#define UCB_RISING     (1 << 0)
+#define UCB_FALLING    (1 << 1)
+
+int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
+void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
+void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
+int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
+
+#endif
index 7501fab349e4ce5271cbe7b517b2f32f945ed954..46de5c9405557b0ddb1166f397539b94742bc38b 100644 (file)
@@ -192,22 +192,37 @@ static int hdpu_cpustate_probe(struct device *ddev)
 {
        struct platform_device *pdev = to_platform_device(ddev);
        struct resource *res;
+       struct proc_dir_entry *proc_de;
+       int ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        cpustate.set_addr = (unsigned long *)res->start;
        cpustate.clr_addr = (unsigned long *)res->end - 1;
 
-       misc_register(&cpustate_dev);
-       create_proc_read_entry("sky_cpustate", 0, 0, cpustate_read_proc, NULL);
+       ret = misc_register(&cpustate_dev);
+       if (ret) {
+               printk(KERN_WARNING "sky_cpustate: Unable to register misc "
+                                       "device.\n");
+               cpustate.set_addr = NULL;
+               cpustate.clr_addr = NULL;
+               return ret;
+       }
+
+       proc_de = create_proc_read_entry("sky_cpustate", 0, 0,
+                                       cpustate_read_proc, NULL);
+       if (proc_de == NULL)
+               printk(KERN_WARNING "sky_cpustate: Unable to create proc "
+                                       "dir entry\n");
 
        printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
        return 0;
 }
+
 static int hdpu_cpustate_remove(struct device *ddev)
 {
 
-       cpustate.set_addr = 0;
-       cpustate.clr_addr = 0;
+       cpustate.set_addr = NULL;
+       cpustate.clr_addr = NULL;
 
        remove_proc_entry("sky_cpustate", NULL);
        misc_deregister(&cpustate_dev);
index a62c86fef5ccc094f8a5e65ee0375837d14548e2..e11e55dc89249279fdbc9fb8c1c807cfb3e74dc1 100644 (file)
@@ -1111,20 +1111,6 @@ static void wbsd_reset_ignore(unsigned long data)
        spin_unlock_bh(&host->lock);
 }
 
-/*
- * Helper function for card detection
- */
-static void wbsd_detect_card(unsigned long data)
-{
-       struct wbsd_host *host = (struct wbsd_host*)data;
-       
-       BUG_ON(host == NULL);
-       
-       DBG("Executing card detection\n");
-       
-       mmc_detect_change(host->mmc, 0);        
-}
-
 /*
  * Tasklets
  */
@@ -1169,14 +1155,16 @@ static void wbsd_tasklet_card(unsigned long param)
                        DBG("Card inserted\n");
                        host->flags |= WBSD_FCARD_PRESENT;
                        
+                       spin_unlock(&host->lock);
+
                        /*
                         * Delay card detection to allow electrical connections
                         * to stabilise.
                         */
-                       mod_timer(&host->detect_timer, jiffies + HZ/2);
+                       mmc_detect_change(host->mmc, msecs_to_jiffies(500));
                }
-               
-               spin_unlock(&host->lock);
+               else
+                       spin_unlock(&host->lock);
        }
        else if (host->flags & WBSD_FCARD_PRESENT)
        {
@@ -1409,10 +1397,6 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
        /*
         * Set up timers
         */
-       init_timer(&host->detect_timer);
-       host->detect_timer.data = (unsigned long)host;
-       host->detect_timer.function = wbsd_detect_card;
-
        init_timer(&host->ignore_timer);
        host->ignore_timer.data = (unsigned long)host;
        host->ignore_timer.function = wbsd_reset_ignore;
@@ -1454,7 +1438,6 @@ static void __devexit wbsd_free_mmc(struct device* dev)
        BUG_ON(host == NULL);
        
        del_timer_sync(&host->ignore_timer);
-       del_timer_sync(&host->detect_timer);
        
        mmc_free_host(mmc);
        
index bb713fed2f373c66fd13e8f29be3abbc733963bb..1443117fd8f4afb988becd36beb1d14a084c5646 100644 (file)
@@ -91,8 +91,7 @@ static void __exit cleanup_mtdram(void)
 {
        if (mtd_info) {
                del_mtd_device(mtd_info);
-               if (mtd_info->priv)
-                       vfree(mtd_info->priv);
+               vfree(mtd_info->priv);
                kfree(mtd_info);
        }
 }
index d9ab60b36fd43d571995165d3df190fdbebbb01b..d32c1b3a8ce34422bd7c476b80299beef40ebb67 100644 (file)
@@ -1017,27 +1017,16 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
 
 void ftl_freepart(partition_t *part)
 {
-    if (part->VirtualBlockMap) {
        vfree(part->VirtualBlockMap);
        part->VirtualBlockMap = NULL;
-    }
-    if (part->VirtualPageMap) {
        kfree(part->VirtualPageMap);
        part->VirtualPageMap = NULL;
-    }
-    if (part->EUNInfo) {
        kfree(part->EUNInfo);
        part->EUNInfo = NULL;
-    }
-    if (part->XferInfo) {
        kfree(part->XferInfo);
        part->XferInfo = NULL;
-    }
-    if (part->bam_cache) {
        kfree(part->bam_cache);
        part->bam_cache = NULL;
-    }
-    
 } /* ftl_freepart */
 
 static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
index 811d92e5f5b1426c83bd0f1992ee00859227733b..cc372136e852750f87f42dd3d69c0d917d074908 100644 (file)
@@ -23,9 +23,6 @@
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
 
-/****************************************************************************/
-
-
 /****************************************************************************/
 
 struct map_info uclinux_ram_map = {
@@ -60,14 +57,15 @@ int __init uclinux_mtd_init(void)
        struct mtd_info *mtd;
        struct map_info *mapp;
        extern char _ebss;
+       unsigned long addr = (unsigned long) &_ebss;
 
        mapp = &uclinux_ram_map;
-       mapp->phys = (unsigned long) &_ebss;
-       mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8)));
+       mapp->phys = addr;
+       mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(addr + 8))));
        mapp->bankwidth = 4;
 
        printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
-               (int) mapp->map_priv_2, (int) mapp->size);
+               (int) mapp->phys, (int) mapp->size);
 
        mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
 
@@ -95,7 +93,6 @@ int __init uclinux_mtd_init(void)
        printk("uclinux[mtd]: set %s to be root filesystem\n",
                uclinux_romfs[0].name);
        ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
-       put_mtd_device(mtd);
 
        return(0);
 }
@@ -109,7 +106,7 @@ void __exit uclinux_mtd_cleanup(void)
                map_destroy(uclinux_ram_mtdinfo);
                uclinux_ram_mtdinfo = NULL;
        }
-       if (uclinux_ram_map.map_priv_1) {
+       if (uclinux_ram_map.virt) {
                iounmap((void *) uclinux_ram_map.virt);
                uclinux_ram_map.virt = 0;
        }
index 6bb9232514b4e95a1b6506fe792e61a5f46779e5..54fff9c2e8028cb0a7509dae5cb5ed017bab39ab 100644 (file)
@@ -1738,11 +1738,18 @@ config 68360_ENET
          the Motorola 68360 processor.
 
 config FEC
-       bool "FEC ethernet controller (of ColdFire 5272)"
-       depends on M5272 || M5282
+       bool "FEC ethernet controller (of ColdFire CPUs)"
+       depends on M523x || M527x || M5272 || M528x
        help
          Say Y here if you want to use the built-in 10/100 Fast ethernet
-         controller on the Motorola ColdFire 5272 processor.
+         controller on some Motorola ColdFire processors.
+
+config FEC2
+       bool "Second FEC ethernet controller (on some ColdFire CPUs)"
+       depends on FEC
+       help
+         Say Y here if you want to use the second built-in 10/100 Fast
+         ethernet controller on some Motorola ColdFire processors.
 
 config NE_H8300
        tristate "NE2000 compatible support for H8/300"
index 1798ce7262c9b0b0ddea69042646abc5827c8bf8..0095384ff45420c1cd04111fa04ea35a3d365865 100644 (file)
@@ -155,7 +155,7 @@ static int bionet_close(struct net_device *dev);
 static struct net_device_stats *net_get_stats(struct net_device *dev);
 static void bionet_tick(unsigned long);
 
-static struct timer_list bionet_timer = TIMER_INITIALIZER(bionet_tick, 0, 0);
+static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0);
 
 #define STRAM_ADDR(a)  (((a) & 0xff000000) == 0)
 
index 81c362c8cb973949557550a89e45b45c2268aa3f..8b997809f9de2db86a31a9db66399c7ceb1430a0 100644 (file)
@@ -165,7 +165,7 @@ static void pamsnet_tick(unsigned long);
 
 static irqreturn_t pamsnet_intr(int irq, void *data, struct pt_regs *fp);
 
-static struct timer_list pamsnet_timer = TIMER_INITIALIZER(pamsnet_tick, 0, 0);
+static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0);
 
 #define STRAM_ADDR(a)  (((a) & 0xff000000) == 0)
 
index 3d88ad622bdb35faf267fcc2d4e21e04628af9eb..fb4098ed469eeb8a2be64d6754cddda98e640324 100644 (file)
@@ -323,33 +323,27 @@ static void bsd_reset (void *state)
  */
 
 static void bsd_free (void *state)
-  {
-    struct bsd_db *db = (struct bsd_db *) state;
+{
+       struct bsd_db *db = state;
     
-    if (db)
-      {
+       if (!db)
+               return;
+
 /*
  * Release the dictionary
  */
-       if (db->dict)
-         {
-           vfree (db->dict);
-           db->dict = NULL;
-         }
+       vfree(db->dict);
+       db->dict = NULL;
 /*
  * Release the string buffer
  */
-       if (db->lens)
-         {
-           vfree (db->lens);
-           db->lens = NULL;
-         }
+       vfree(db->lens);
+       db->lens = NULL;
 /*
  * Finally release the structure itself.
  */
-       kfree (db);
-      }
-  }
+       kfree(db);
+}
 
 /*
  * Allocate space for a (de) compressor.
index 442670860fca279afb9ef78fdaf79b6a16a493bd..b68b9cad76e9d3952ab998038e77789f9101986f 100644 (file)
@@ -384,8 +384,8 @@ static unsigned int mdio_phy_addr; /* Transciever address */
 static unsigned int network_tr_ctrl_shadow = 0;
 
 /* Network speed indication. */
-static struct timer_list speed_timer = TIMER_INITIALIZER(NULL, 0, 0);
-static struct timer_list clear_led_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(speed_timer, NULL, 0, 0);
+static DEFINE_TIMER(clear_led_timer, NULL, 0, 0);
 static int current_speed; /* Speed read from transceiver */
 static int current_speed_selection; /* Speed selected by user */
 static unsigned long led_next_time;
@@ -393,7 +393,7 @@ static int led_active;
 static int rx_queue_len;
 
 /* Duplex */
-static struct timer_list duplex_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(duplex_timer, NULL, 0, 0);
 static int full_duplex;
 static enum duplex current_duplex;
 
index b780307093eb1aadb1d312b186b7168e945753a2..cdc07ccd7332fb7b4b9e006bf0625331cce5729a 100644 (file)
@@ -247,6 +247,9 @@ static int get_eeprom_data(struct net_device *dev, int off, int len, int *buffer
 static int get_eeprom_cksum(int off, int len, int *buffer);
 static int set_mac_address(struct net_device *dev, void *addr);
 static void count_rx_errors(int status, struct net_local *lp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void net_poll_controller(struct net_device *dev);
+#endif
 #if ALLOW_DMA
 static void get_dma_channel(struct net_device *dev);
 static void release_dma_buff(struct net_local *lp);
@@ -405,6 +408,19 @@ get_eeprom_cksum(int off, int len, int *buffer)
        return -1;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void net_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       net_interrupt(dev->irq, dev, NULL);
+       enable_irq(dev->irq);
+}
+#endif
+
 /* This is the real probe routine.  Linux has a history of friendly device
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.
@@ -760,6 +776,9 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
        dev->get_stats          = net_get_stats;
        dev->set_multicast_list = set_multicast_list;
        dev->set_mac_address    = set_mac_address;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller    = net_poll_controller;
+#endif
 
        printk("\n");
        if (net_debug)
index 2c7008491378fef4cf71050582e6f88fb9f3e3c7..85504fb900dab5a62402a2ddc60e7ec5febe52e3 100644 (file)
@@ -8,7 +8,7 @@
  * describes connections using the internal parallel port I/O, which
  * is basically all of Port D.
  *
- * Right now, I am very watseful with the buffers.  I allocate memory
+ * Right now, I am very wasteful with the buffers.  I allocate memory
  * pages and then divide them into 2K frame buffers.  This way I know I
  * have buffers large enough to hold one frame within one buffer descriptor.
  * Once I get this working, I will use 64 or 128 byte CPM buffers, which
  * Copyright (c) 2000 Ericsson Radio Systems AB.
  *
  * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
- * Copyrught (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ *
+ * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
+ * Copyright (c) 2004-2005 Macq Electronique SA.
  */
 
 #include <linux/config.h>
@@ -46,7 +49,8 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M5272) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
+    defined(CONFIG_M5272) || defined(CONFIG_M528x)
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include "fec.h"
@@ -71,7 +75,7 @@ static unsigned int fec_hw[] = {
 #elif defined(CONFIG_M527x)
        (MCF_MBAR + 0x1000),
        (MCF_MBAR + 0x1800),
-#elif defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
        (MCF_MBAR + 0x1000),
 #else
        &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
@@ -94,12 +98,14 @@ static unsigned char        fec_mac_default[] = {
 #define        FEC_FLASHMAC    0xffe04000
 #elif defined(CONFIG_CANCam)
 #define        FEC_FLASHMAC    0xf0020000
+#elif defined (CONFIG_M5272C3)
+#define        FEC_FLASHMAC    (0xffe04000 + 4)
+#elif defined(CONFIG_MOD5272)
+#define FEC_FLASHMAC   0xffc0406b
 #else
 #define        FEC_FLASHMAC    0
 #endif
 
-unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC;
-
 /* Forward declarations of some structures to support different PHYs
 */
 
@@ -158,7 +164,7 @@ typedef struct {
  * size bits. Other FEC hardware does not, so we need to take that into
  * account when setting it.
  */
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define        OPT_FRAME_SIZE  (PKT_MAXBUF_SIZE << 16)
 #else
 #define        OPT_FRAME_SIZE  0
@@ -196,7 +202,7 @@ struct fec_enet_private {
        uint    phy_id_done;
        uint    phy_status;
        uint    phy_speed;
-       phy_info_t      *phy;
+       phy_info_t const        *phy;
        struct work_struct phy_task;
 
        uint    sequence_done;
@@ -209,7 +215,6 @@ struct fec_enet_private {
        int     link;
        int     old_link;
        int     full_duplex;
-       unsigned char mac_addr[ETH_ALEN];
 };
 
 static int fec_enet_open(struct net_device *dev);
@@ -237,10 +242,10 @@ typedef struct mii_list {
 } mii_list_t;
 
 #define                NMII    20
-mii_list_t     mii_cmds[NMII];
-mii_list_t     *mii_free;
-mii_list_t     *mii_head;
-mii_list_t     *mii_tail;
+static mii_list_t      mii_cmds[NMII];
+static mii_list_t      *mii_free;
+static mii_list_t      *mii_head;
+static mii_list_t      *mii_tail;
 
 static int     mii_queue(struct net_device *dev, int request, 
                                void (*func)(uint, struct net_device *));
@@ -425,7 +430,7 @@ fec_timeout(struct net_device *dev)
        }
        }
 #endif
-       fec_restart(dev, 0);
+       fec_restart(dev, fep->full_duplex);
        netif_wake_queue(dev);
 }
 
@@ -757,45 +762,52 @@ static void mii_parse_sr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+       status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
 
        if (mii_reg & 0x0004)
-               *s |= PHY_STAT_LINK;
+               status |= PHY_STAT_LINK;
        if (mii_reg & 0x0010)
-               *s |= PHY_STAT_FAULT;
+               status |= PHY_STAT_FAULT;
        if (mii_reg & 0x0020)
-               *s |= PHY_STAT_ANC;
+               status |= PHY_STAT_ANC;
+
+       *s = status;
 }
 
 static void mii_parse_cr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+       status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
 
        if (mii_reg & 0x1000)
-               *s |= PHY_CONF_ANE;
+               status |= PHY_CONF_ANE;
        if (mii_reg & 0x4000)
-               *s |= PHY_CONF_LOOP;
+               status |= PHY_CONF_LOOP;
+       *s = status;
 }
 
 static void mii_parse_anar(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_CONF_SPMASK);
+       status = *s & ~(PHY_CONF_SPMASK);
 
        if (mii_reg & 0x0020)
-               *s |= PHY_CONF_10HDX;
+               status |= PHY_CONF_10HDX;
        if (mii_reg & 0x0040)
-               *s |= PHY_CONF_10FDX;
+               status |= PHY_CONF_10FDX;
        if (mii_reg & 0x0080)
-               *s |= PHY_CONF_100HDX;
+               status |= PHY_CONF_100HDX;
        if (mii_reg & 0x00100)
-               *s |= PHY_CONF_100FDX;
+               status |= PHY_CONF_100FDX;
+       *s = status;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -811,37 +823,34 @@ static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK);
-
+       status = *s & ~(PHY_STAT_SPMASK);
        if (mii_reg & 0x0800) {
                if (mii_reg & 0x1000)
-                       *s |= PHY_STAT_100FDX;
+                       status |= PHY_STAT_100FDX;
                else
-                       *s |= PHY_STAT_100HDX;
+                       status |= PHY_STAT_100HDX;
        } else {
                if (mii_reg & 0x1000)
-                       *s |= PHY_STAT_10FDX;
+                       status |= PHY_STAT_10FDX;
                else
-                       *s |= PHY_STAT_10HDX;
+                       status |= PHY_STAT_10HDX;
        }
+       *s = status;
 }
 
-static phy_info_t phy_info_lxt970 = {
-       0x07810000, 
-       "LXT970",
-
-       (const phy_cmd_t []) {  /* config */
+static phy_cmd_t const phy_cmd_lxt970_config[] = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt970_startup[] = { /* enable interrupts */
                { mk_mii_write(MII_LXT970_IER, 0x0002), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_lxt970_ack_int[] = {
                /* read SR and ISR to acknowledge */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                { mk_mii_read(MII_LXT970_ISR), NULL },
@@ -849,11 +858,18 @@ static phy_info_t phy_info_lxt970 = {
                /* find out the current status */
                { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt970_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_LXT970_IER, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_lxt970 = {
+       .id = 0x07810000, 
+       .name = "LXT970",
+       .config = phy_cmd_lxt970_config,
+       .startup = phy_cmd_lxt970_startup,
+       .ack_int = phy_cmd_lxt970_ack_int,
+       .shutdown = phy_cmd_lxt970_shutdown
 };
        
 /* ------------------------------------------------------------------------- */
@@ -878,45 +894,44 @@ static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+       status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
 
        if (mii_reg & 0x0400) {
                fep->link = 1;
-               *s |= PHY_STAT_LINK;
+               status |= PHY_STAT_LINK;
        } else {
                fep->link = 0;
        }
        if (mii_reg & 0x0080)
-               *s |= PHY_STAT_ANC;
+               status |= PHY_STAT_ANC;
        if (mii_reg & 0x4000) {
                if (mii_reg & 0x0200)
-                       *s |= PHY_STAT_100FDX;
+                       status |= PHY_STAT_100FDX;
                else
-                       *s |= PHY_STAT_100HDX;
+                       status |= PHY_STAT_100HDX;
        } else {
                if (mii_reg & 0x0200)
-                       *s |= PHY_STAT_10FDX;
+                       status |= PHY_STAT_10FDX;
                else
-                       *s |= PHY_STAT_10HDX;
+                       status |= PHY_STAT_10HDX;
        }
        if (mii_reg & 0x0008)
-               *s |= PHY_STAT_FAULT;
-}
+               status |= PHY_STAT_FAULT;
 
-static phy_info_t phy_info_lxt971 = {
-       0x0001378e, 
-       "LXT971",
+       *s = status;
+}
        
-       (const phy_cmd_t []) {  /* config */  
-               /* limit to 10MBit because my protorype board 
+static phy_cmd_t const phy_cmd_lxt971_config[] = {
+               /* limit to 10MBit because my prototype board 
                 * doesn't work with 100. */
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt971_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */
@@ -925,19 +940,26 @@ static phy_info_t phy_info_lxt971 = {
                 * read here to get a valid value in ack_int */
                { mk_mii_read(MII_REG_SR), mii_parse_sr }, 
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_lxt971_ack_int[] = {
+               /* acknowledge the int before reading status ! */
+               { mk_mii_read(MII_LXT971_ISR), NULL },
                /* find out the current status */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
-               /* we only need to read ISR to acknowledge */
-               { mk_mii_read(MII_LXT971_ISR), NULL },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_lxt971_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_lxt971 = {
+       .id = 0x0001378e, 
+       .name = "LXT971",
+       .config = phy_cmd_lxt971_config,
+       .startup = phy_cmd_lxt971_startup,
+       .ack_int = phy_cmd_lxt971_ack_int,
+       .shutdown = phy_cmd_lxt971_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
@@ -956,22 +978,21 @@ static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK);
+       status = *s & ~(PHY_STAT_SPMASK);
 
        switch((mii_reg >> 2) & 7) {
-       case 1: *s |= PHY_STAT_10HDX; break;
-       case 2: *s |= PHY_STAT_100HDX; break;
-       case 5: *s |= PHY_STAT_10FDX; break;
-       case 6: *s |= PHY_STAT_100FDX; break;
-       }
+       case 1: status |= PHY_STAT_10HDX; break;
+       case 2: status |= PHY_STAT_100HDX; break;
+       case 5: status |= PHY_STAT_10FDX; break;
+       case 6: status |= PHY_STAT_100FDX; break;
 }
 
-static phy_info_t phy_info_qs6612 = {
-       0x00181440, 
-       "QS6612",
-       
-       (const phy_cmd_t []) {  /* config */  
+       *s = status;
+}
+
+static phy_cmd_t const phy_cmd_qs6612_config[] = {
                /* The PHY powers up isolated on the RPX, 
                 * so send a command to allow operation.
                 */
@@ -981,13 +1002,13 @@ static phy_info_t phy_info_qs6612 = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_qs6612_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_qs6612_ack_int[] = {
                /* we need to read ISR, SR and ANER to acknowledge */
                { mk_mii_read(MII_QS6612_ISR), NULL },
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
@@ -996,11 +1017,18 @@ static phy_info_t phy_info_qs6612 = {
                /* read pcr to get info */
                { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_qs6612_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_qs6612 = {
+       .id = 0x00181440, 
+       .name = "QS6612",
+       .config = phy_cmd_qs6612_config,
+       .startup = phy_cmd_qs6612_startup,
+       .ack_int = phy_cmd_qs6612_ack_int,
+       .shutdown = phy_cmd_qs6612_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
@@ -1020,49 +1048,54 @@ static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile uint *s = &(fep->phy_status);
+       uint status;
 
-       *s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
+       status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
 
        if (mii_reg & 0x0080)
-               *s |= PHY_STAT_ANC;
+               status |= PHY_STAT_ANC;
        if (mii_reg & 0x0400)
-               *s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
+               status |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX);
        else
-               *s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+               status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
+
+       *s = status;
 }
 
-static phy_info_t phy_info_am79c874 = {
-       0x00022561, 
-       "AM79C874",
-       
-       (const phy_cmd_t []) {  /* config */  
-               /* limit to 10MBit because my protorype board 
-                * doesn't work with 100. */
+static phy_cmd_t const phy_cmd_am79c874_config[] = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup - enable interrupts */
+       };
+static phy_cmd_t const phy_cmd_am79c874_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_read(MII_REG_SR), mii_parse_sr }, 
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_am79c874_ack_int[] = {
                /* find out the current status */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr },
                /* we only need to read ISR to acknowledge */
                { mk_mii_read(MII_AM79C874_ICSR), NULL },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown - disable interrupts */
+       };
+static phy_cmd_t const phy_cmd_am79c874_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_am79c874 = {
+       .id = 0x00022561,
+       .name = "AM79C874",
+       .config = phy_cmd_am79c874_config,
+       .startup = phy_cmd_am79c874_startup,
+       .ack_int = phy_cmd_am79c874_ack_int,
+       .shutdown = phy_cmd_am79c874_shutdown
 };
 
+
 /* ------------------------------------------------------------------------- */
 /* Kendin KS8721BL phy                                                       */
 
@@ -1072,37 +1105,40 @@ static phy_info_t phy_info_am79c874 = {
 #define MII_KS8721BL_ICSR      22
 #define        MII_KS8721BL_PHYCR      31
 
-static phy_info_t phy_info_ks8721bl = {
-       0x00022161, 
-       "KS8721BL",
-       
-       (const phy_cmd_t []) {  /* config */  
+static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
                { mk_mii_read(MII_REG_CR), mii_parse_cr },
                { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* startup */
+       };
+static phy_cmd_t const phy_cmd_ks8721bl_startup[] = {  /* enable interrupts */
                { mk_mii_write(MII_KS8721BL_ICSR, 0xff00), NULL },
                { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
                { mk_mii_read(MII_REG_SR), mii_parse_sr }, 
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) { /* ack_int */
+       };
+static phy_cmd_t const phy_cmd_ks8721bl_ack_int[] = {
                /* find out the current status */
                { mk_mii_read(MII_REG_SR), mii_parse_sr },
                /* we only need to read ISR to acknowledge */
                { mk_mii_read(MII_KS8721BL_ICSR), NULL },
                { mk_mii_end, }
-       },
-       (const phy_cmd_t []) {  /* shutdown */
+       };
+static phy_cmd_t const phy_cmd_ks8721bl_shutdown[] = { /* disable interrupts */
                { mk_mii_write(MII_KS8721BL_ICSR, 0x0000), NULL },
                { mk_mii_end, }
-       },
+       };
+static phy_info_t const phy_info_ks8721bl = {
+       .id = 0x00022161, 
+       .name = "KS8721BL",
+       .config = phy_cmd_ks8721bl_config,
+       .startup = phy_cmd_ks8721bl_startup,
+       .ack_int = phy_cmd_ks8721bl_ack_int,
+       .shutdown = phy_cmd_ks8721bl_shutdown
 };
 
 /* ------------------------------------------------------------------------- */
 
-static phy_info_t *phy_info[] = {
+static phy_info_t const * const phy_info[] = {
        &phy_info_lxt970,
        &phy_info_lxt971,
        &phy_info_qs6612,
@@ -1129,16 +1165,23 @@ mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
        volatile unsigned long *icrp;
+       static const struct idesc {
+               char *name;
+               unsigned short irq;
+               irqreturn_t (*handler)(int, void *, struct pt_regs *);
+       } *idp, id[] = {
+               { "fec(RX)", 86, fec_enet_interrupt },
+               { "fec(TX)", 87, fec_enet_interrupt },
+               { "fec(OTHER)", 88, fec_enet_interrupt },
+               { "fec(MII)", 66, mii_link_interrupt },
+               { NULL },
+       };
 
        /* Setup interrupt handlers. */
-       if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n");
-       if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n");
-       if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0)
-               printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n");
-       if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0)
-               printk("FEC: Could not allocate MII IRQ(66)!\n");
+       for (idp = id; idp->name; idp++) {
+               if (request_irq(idp->irq, idp->handler, 0, idp->name, dev) != 0)
+                       printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, idp->irq);
+       }
 
        /* Unmask interrupt at ColdFire 5272 SIM */
        icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3);
@@ -1169,17 +1212,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile fec_t *fecp;
-       unsigned char *iap, tmpaddr[6];
-       int i;
+       unsigned char *iap, tmpaddr[ETH_ALEN];
 
        fecp = fep->hwp;
 
-       if (fec_flashmac) {
+       if (FEC_FLASHMAC) {
                /*
                 * Get MAC address from FLASH.
                 * If it is all 1's or 0's, use the default.
                 */
-               iap = fec_flashmac;
+               iap = (unsigned char *)FEC_FLASHMAC;
                if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
                    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
                        iap = fec_mac_default;
@@ -1192,14 +1234,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                iap = &tmpaddr[0];
        }
 
-       for (i=0; i<ETH_ALEN; i++)
-               dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+       memcpy(dev->dev_addr, iap, ETH_ALEN);
 
        /* Adjust MAC if using default MAC address */
-       if (iap == fec_mac_default) {
-               dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
-                       iap[ETH_ALEN-1] + fep->index;
-       }
+       if (iap == fec_mac_default)
+                dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
@@ -1234,48 +1273,44 @@ static void __inline__ fec_uncache(unsigned long addr)
 
 /* ------------------------------------------------------------------------- */
 
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 
 /*
- *     Code specific to Coldfire 5270/5271/5274/5275 and 5280/5282 setups.
+ *     Code specific to Coldfire 5230/5231/5232/5234/5235,
+ *     the 5270/5271/5274/5275 and 5280/5282 setups.
  */
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
        struct fec_enet_private *fep;
        int b;
+       static const struct idesc {
+               char *name;
+               unsigned short irq;
+       } *idp, id[] = {
+               { "fec(TXF)", 23 },
+               { "fec(TXB)", 24 },
+               { "fec(TXFIFO)", 25 },
+               { "fec(TXCR)", 26 },
+               { "fec(RXF)", 27 },
+               { "fec(RXB)", 28 },
+               { "fec(MII)", 29 },
+               { "fec(LC)", 30 },
+               { "fec(HBERR)", 31 },
+               { "fec(GRA)", 32 },
+               { "fec(EBERR)", 33 },
+               { "fec(BABT)", 34 },
+               { "fec(BABR)", 35 },
+               { NULL },
+       };
 
        fep = netdev_priv(dev);
        b = (fep->index) ? 128 : 64;
 
        /* Setup interrupt handlers. */
-       if (request_irq(b+23, fec_enet_interrupt, 0, "fec(TXF)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXF) IRQ(%d+23)!\n", b);
-       if (request_irq(b+24, fec_enet_interrupt, 0, "fec(TXB)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXB) IRQ(%d+24)!\n", b);
-       if (request_irq(b+25, fec_enet_interrupt, 0, "fec(TXFIFO)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXFIFO) IRQ(%d+25)!\n", b);
-       if (request_irq(b+26, fec_enet_interrupt, 0, "fec(TXCR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(TXCR) IRQ(%d+26)!\n", b);
-
-       if (request_irq(b+27, fec_enet_interrupt, 0, "fec(RXF)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RXF) IRQ(%d+27)!\n", b);
-       if (request_irq(b+28, fec_enet_interrupt, 0, "fec(RXB)", dev) != 0)
-               printk("FEC: Could not allocate FEC(RXB) IRQ(%d+28)!\n", b);
-
-       if (request_irq(b+29, fec_enet_interrupt, 0, "fec(MII)", dev) != 0)
-               printk("FEC: Could not allocate FEC(MII) IRQ(%d+29)!\n", b);
-       if (request_irq(b+30, fec_enet_interrupt, 0, "fec(LC)", dev) != 0)
-               printk("FEC: Could not allocate FEC(LC) IRQ(%d+30)!\n", b);
-       if (request_irq(b+31, fec_enet_interrupt, 0, "fec(HBERR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(HBERR) IRQ(%d+31)!\n", b);
-       if (request_irq(b+32, fec_enet_interrupt, 0, "fec(GRA)", dev) != 0)
-               printk("FEC: Could not allocate FEC(GRA) IRQ(%d+32)!\n", b);
-       if (request_irq(b+33, fec_enet_interrupt, 0, "fec(EBERR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(EBERR) IRQ(%d+33)!\n", b);
-       if (request_irq(b+34, fec_enet_interrupt, 0, "fec(BABT)", dev) != 0)
-               printk("FEC: Could not allocate FEC(BABT) IRQ(%d+34)!\n", b);
-       if (request_irq(b+35, fec_enet_interrupt, 0, "fec(BABR)", dev) != 0)
-               printk("FEC: Could not allocate FEC(BABR) IRQ(%d+35)!\n", b);
+       for (idp = id; idp->name; idp++) {
+               if (request_irq(b+idp->irq, fec_enet_interrupt, 0, idp->name, dev) != 0)
+                       printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
+       }
 
        /* Unmask interrupts at ColdFire 5280/5282 interrupt controller */
        {
@@ -1300,11 +1335,13 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
 #if defined(CONFIG_M528x)
        /* Set up gpio outputs for MII lines */
        {
-               volatile unsigned short *gpio_paspar;
+               volatile u16 *gpio_paspar;
+               volatile u8 *gpio_pehlpar;
   
-               gpio_paspar = (volatile unsigned short *) (MCF_IPSBAR +
-                       0x100056);
-               *gpio_paspar = 0x0f00;
+               gpio_paspar = (volatile u16 *) (MCF_IPSBAR + 0x100056);
+               gpio_pehlpar = (volatile u16 *) (MCF_IPSBAR + 0x100058);
+               *gpio_paspar |= 0x0f00;
+               *gpio_pehlpar = 0xc0;
        }
 #endif
 }
@@ -1331,17 +1368,16 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        volatile fec_t *fecp;
-       unsigned char *iap, tmpaddr[6];
-       int i;
+       unsigned char *iap, tmpaddr[ETH_ALEN];
 
        fecp = fep->hwp;
 
-       if (fec_flashmac) {
+       if (FEC_FLASHMAC) {
                /*
                 * Get MAC address from FLASH.
                 * If it is all 1's or 0's, use the default.
                 */
-               iap = fec_flashmac;
+               iap = FEC_FLASHMAC;
                if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
                    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
                        iap = fec_mac_default;
@@ -1354,14 +1390,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
                iap = &tmpaddr[0];
        }
 
-       for (i=0; i<ETH_ALEN; i++)
-               dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
+       memcpy(dev->dev_addr, iap, ETH_ALEN);
 
        /* Adjust MAC if using default MAC address */
-       if (iap == fec_mac_default) {
-               dev->dev_addr[ETH_ALEN-1] = fep->mac_addr[ETH_ALEN-1] =
-                       iap[ETH_ALEN-1] + fep->index;
-       }
+       if (iap == fec_mac_default)
+               dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
@@ -1392,7 +1425,7 @@ static void __inline__ fec_uncache(unsigned long addr)
 #else
 
 /*
- *     Code sepcific to the MPC860T setup.
+ *     Code specific to the MPC860T setup.
  */
 static void __inline__ fec_request_intrs(struct net_device *dev)
 {
@@ -1424,13 +1457,10 @@ static void __inline__ fec_request_intrs(struct net_device *dev)
 
 static void __inline__ fec_get_mac(struct net_device *dev)
 {
-       struct fec_enet_private *fep = netdev_priv(dev);
-       unsigned char *iap, tmpaddr[6];
        bd_t *bd;
-       int i;
 
-       iap = bd->bi_enetaddr;
        bd = (bd_t *)__res;
+       memcpy(dev->dev_addr, bd->bi_enetaddr, ETH_ALEN);
 
 #ifdef CONFIG_RPXCLASSIC
        /* The Embedded Planet boards have only one MAC address in
@@ -1439,14 +1469,8 @@ static void __inline__ fec_get_mac(struct net_device *dev)
         * the address bits above something that would have (up to
         * now) been allocated.
         */
-       for (i=0; i<6; i++)
-               tmpaddr[i] = *iap++;
-       tmpaddr[3] |= 0x80;
-       iap = tmpaddr;
+       dev->dev_adrd[3] |= 0x80;
 #endif
-
-       for (i=0; i<6; i++)
-               dev->dev_addr[i] = fep->mac_addr[i] = *iap++;
 }
 
 static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
@@ -1556,7 +1580,7 @@ static void mii_display_status(struct net_device *dev)
 static void mii_display_config(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
-       volatile uint *s = &(fep->phy_status);
+       uint status = fep->phy_status;
 
        /*
        ** When we get here, phy_task is already removed from
@@ -1565,23 +1589,23 @@ static void mii_display_config(struct net_device *dev)
        fep->mii_phy_task_queued = 0;
        printk("%s: config: auto-negotiation ", dev->name);
 
-       if (*s & PHY_CONF_ANE)
+       if (status & PHY_CONF_ANE)
                printk("on");
        else
                printk("off");
 
-       if (*s & PHY_CONF_100FDX)
+       if (status & PHY_CONF_100FDX)
                printk(", 100FDX");
-       if (*s & PHY_CONF_100HDX)
+       if (status & PHY_CONF_100HDX)
                printk(", 100HDX");
-       if (*s & PHY_CONF_10FDX)
+       if (status & PHY_CONF_10FDX)
                printk(", 10FDX");
-       if (*s & PHY_CONF_10HDX)
+       if (status & PHY_CONF_10HDX)
                printk(", 10HDX");
-       if (!(*s & PHY_CONF_SPMASK))
+       if (!(status & PHY_CONF_SPMASK))
                printk(", No speed/duplex selected?");
 
-       if (*s & PHY_CONF_LOOP)
+       if (status & PHY_CONF_LOOP)
                printk(", loopback enabled");
        
        printk(".\n");
@@ -1639,7 +1663,7 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev)
        schedule_work(&fep->phy_task);
 }
 
-/* mii_queue_config is called in user context from fec_enet_open */
+/* mii_queue_config is called in interrupt context from fec_enet_mii */
 static void mii_queue_config(uint mii_reg, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
@@ -1652,14 +1676,14 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev)
        schedule_work(&fep->phy_task);
 }
 
-
-
-phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink },
-                              { mk_mii_end, } };
-phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config },
-                              { mk_mii_end, } };
-
-
+phy_cmd_t const phy_cmd_relink[] = {
+       { mk_mii_read(MII_REG_CR), mii_queue_relink },
+       { mk_mii_end, }
+       };
+phy_cmd_t const phy_cmd_config[] = {
+       { mk_mii_read(MII_REG_CR), mii_queue_config },
+       { mk_mii_end, }
+       };
 
 /* Read remainder of PHY ID.
 */
@@ -1897,17 +1921,15 @@ static void set_multicast_list(struct net_device *dev)
 static void
 fec_set_mac_address(struct net_device *dev)
 {
-       struct fec_enet_private *fep;
        volatile fec_t *fecp;
 
-       fep = netdev_priv(dev);
-       fecp = fep->hwp;
+       fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
 
        /* Set station address. */
-       fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
-               (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
-       fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
-               (fep->mac_addr[4] << 24);
+       fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+               (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
+       fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
+               (dev->dev_addr[4] << 24);
 
 }
 
@@ -1943,7 +1965,7 @@ int __init fec_enet_init(struct net_device *dev)
        udelay(10);
 
        /* Clear and enable interrupts */
-       fecp->fec_ievent = 0xffc0;
+       fecp->fec_ievent = 0xffc00000;
        fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
                FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
        fecp->fec_hash_table_high = 0;
@@ -2063,11 +2085,6 @@ int __init fec_enet_init(struct net_device *dev)
        /* setup MII interface */
        fec_set_mii(dev, fep);
 
-       printk("%s: FEC ENET Version 0.2, ", dev->name);
-       for (i=0; i<5; i++)
-               printk("%02x:", dev->dev_addr[i]);
-       printk("%02x\n", dev->dev_addr[5]);
-
        /* Queue up command to detect the PHY and initialize the
         * remainder of the interface.
         */
@@ -2106,18 +2123,12 @@ fec_restart(struct net_device *dev, int duplex)
 
        /* Clear any outstanding interrupt.
        */
-       fecp->fec_ievent = 0xffc0;
+       fecp->fec_ievent = 0xffc00000;
        fec_enable_phy_intr();
 
        /* Set station address.
        */
-       fecp->fec_addr_low = fep->mac_addr[3] | (fep->mac_addr[2] << 8) |
-               (fep->mac_addr[1] << 16) | (fep->mac_addr[0] << 24);
-       fecp->fec_addr_high = (fep->mac_addr[5] << 16) |
-               (fep->mac_addr[4] << 24);
-
-       for (i=0; i<ETH_ALEN; i++)
-               dev->dev_addr[i] = fep->mac_addr[i];
+       fec_set_mac_address(dev);
 
        /* Reset all multicast.
        */
@@ -2215,7 +2226,7 @@ fec_stop(struct net_device *dev)
 
        fecp->fec_x_cntrl = 0x01;       /* Graceful transmit stop */
 
-       while(!(fecp->fec_ievent & 0x10000000));
+       while(!(fecp->fec_ievent & FEC_ENET_GRA));
 
        /* Whack a reset.  We should wait for this.
        */
@@ -2234,7 +2245,9 @@ fec_stop(struct net_device *dev)
 static int __init fec_enet_module_init(void)
 {
        struct net_device *dev;
-       int i, err;
+       int i, j, err;
+
+       printk("FEC ENET Version 0.2\n");
 
        for (i = 0; (i < FEC_MAX_PORTS); i++) {
                dev = alloc_etherdev(sizeof(struct fec_enet_private));
@@ -2250,6 +2263,11 @@ static int __init fec_enet_module_init(void)
                        free_netdev(dev);
                        return -EIO;
                }
+
+               printk("%s: ethernet ", dev->name);
+               for (j = 0; (j < 5); j++)
+                       printk("%02x:", dev->dev_addr[j]);
+               printk("%02x\n", dev->dev_addr[5]);
        }
        return 0;
 }
index c6e4f979ff5d42a9942d3c1ab57182dfb7935bd1..045761b8a6004ab1f25c73bcd082d00573024589 100644 (file)
@@ -1,8 +1,9 @@
 /****************************************************************************/
 
 /*
- *     fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5270,
-                  5271, 5272, 5274, 5275, 5280 and 5282.
+ *     fec.h  --  Fast Ethernet Controller for Motorola ColdFire 5230,
+ *                5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
+ *                5280 and 5282.
  *
  *     (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
  *     (C) Copyright 2000-2001, Lineo (www.lineo.com)
@@ -13,7 +14,7 @@
 #define        FEC_H
 /****************************************************************************/
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 /*
  *     Just figures, Motorola would have to change the offsets for
  *     registers in the same peripheral device on different models
index 41213ef602dc764bad14bb772684289d1b831f07..f52ee3162c51dc29f2ac586be3dfc610fe3363ee 100644 (file)
@@ -170,7 +170,7 @@ static char ax25_bcast[7] =
 static char ax25_test[7] =
 {'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
 
-static struct timer_list yam_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(yam_timer, NULL, 0, 0);
 
 /* --------------------------------------------------------------------- */
 
index 7c9dbc8c9423ae005a5be12175dc3c33397b367c..25c9a99c377b12142f5014b6e28216a7b5f5e55a 100644 (file)
@@ -94,7 +94,7 @@ static char mv643xx_driver_version[] = "1.0";
 static void __iomem *mv643xx_eth_shared_base;
 
 /* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
-static spinlock_t mv643xx_eth_phy_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mv643xx_eth_phy_lock);
 
 static inline u32 mv_read(int offset)
 {
index bb71638a7c4484a6dfe5b6ba19ad7512ea4e911d..0df7e92b0bf8d587a3b21610ef5d2d1495a6f954 100644 (file)
@@ -1232,9 +1232,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
        navail = 0;     /* total # of usable channels (not deregistered) */
        hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
        i = 0;
-       list = &ppp->channels;
-       while ((list = list->next) != &ppp->channels) {
-               pch = list_entry(list, struct channel, clist);
+       list_for_each_entry(pch, &ppp->channels, clist) {
                navail += pch->avail = (pch->chan != NULL);
                if (pch->avail) {
                        if (skb_queue_empty(&pch->file.xq) ||
@@ -1280,6 +1278,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
 
        /* skip to the channel after the one we last used
           and start at that one */
+       list = &ppp->channels;
        for (i = 0; i < ppp->nxchan; ++i) {
                list = list->next;
                if (list == &ppp->channels) {
@@ -1730,7 +1729,7 @@ static void
 ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
 {
        u32 mask, seq;
-       struct list_head *l;
+       struct channel *ch;
        int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
 
        if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
@@ -1784,8 +1783,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
         * The list of channels can't change because we have the receive
         * side of the ppp unit locked.
         */
-       for (l = ppp->channels.next; l != &ppp->channels; l = l->next) {
-               struct channel *ch = list_entry(l, struct channel, clist);
+       list_for_each_entry(ch, &ppp->channels, clist) {
                if (seq_before(ch->lastseq, seq))
                        seq = ch->lastseq;
        }
@@ -2271,10 +2269,8 @@ static struct compressor_entry *
 find_comp_entry(int proto)
 {
        struct compressor_entry *ce;
-       struct list_head *list = &compressor_list;
 
-       while ((list = list->next) != &compressor_list) {
-               ce = list_entry(list, struct compressor_entry, list);
+       list_for_each_entry(ce, &compressor_list, list) {
                if (ce->comp->compress_proto == proto)
                        return ce;
        }
@@ -2540,20 +2536,15 @@ static struct channel *
 ppp_find_channel(int unit)
 {
        struct channel *pch;
-       struct list_head *list;
 
-       list = &new_channels;
-       while ((list = list->next) != &new_channels) {
-               pch = list_entry(list, struct channel, list);
+       list_for_each_entry(pch, &new_channels, list) {
                if (pch->file.index == unit) {
                        list_del(&pch->list);
                        list_add(&pch->list, &all_channels);
                        return pch;
                }
        }
-       list = &all_channels;
-       while ((list = list->next) != &all_channels) {
-               pch = list_entry(list, struct channel, list);
+       list_for_each_entry(pch, &all_channels, list) {
                if (pch->file.index == unit)
                        return pch;
        }
index 3f67a42e8503f2f3ee243324023fe41319d63ae4..de399563a9db2e02ef20d412820a90bc6e6c00e3 100644 (file)
@@ -2817,7 +2817,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 #if (!defined(__sparc__) && !defined(CONFIG_PPC_PMAC))
 /* Fetch MAC address from vital product data of PCI ROM. */
-static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
+static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char *dev_addr)
 {
        int this_offset;
 
@@ -2838,35 +2838,27 @@ static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, unsigned char
 
                for (i = 0; i < 6; i++)
                        dev_addr[i] = readb(p + i);
-               break;
+               return 1;
        }
+       return 0;
 }
 
 static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
 {
-       u32 rom_reg_orig;
-       void __iomem *p;
-
-       if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
-               if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
-                       goto use_random;
-       }
+       size_t size;
+       void __iomem *p = pci_map_rom(pdev, &size);
 
-       pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
-       pci_write_config_dword(pdev, pdev->rom_base_reg,
-                              rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+       if (p) {
+                       int found;
 
-       p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
-       if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
-               find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
-
-       if (p != NULL)
-               iounmap(p);
-
-       pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
-       return;
+               found = readb(p) == 0x55 &&
+                       readb(p + 1) == 0xaa &&
+                       find_eth_addr_in_vpd(p, (64 * 1024), dev_addr);
+               pci_unmap_rom(pdev, p);
+               if (found)
+                       return;
+       }
 
-use_random:
        /* Sun MAC prefix then 3 random bytes. */
        dev_addr[0] = 0x08;
        dev_addr[1] = 0x00;
index f02fe4119b2c86d5173632048f85bf855604ad66..9f046cae2f71627baefd9fc7644952854d148c9d 100644 (file)
@@ -2954,7 +2954,7 @@ static int is_quattro_p(struct pci_dev *pdev)
 }
 
 /* Fetch MAC address from vital product data of PCI ROM. */
-static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
+static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
 {
        int this_offset;
 
@@ -2977,42 +2977,33 @@ static void find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, uns
 
                        for (i = 0; i < 6; i++)
                                dev_addr[i] = readb(p + i);
-                       break;
+                       return 1;
                }
                index--;
        }
+       return 0;
 }
 
 static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
 {
-       u32 rom_reg_orig;
-       void __iomem *p;
-       int index;
+       size_t size;
+       void __iomem *p = pci_map_rom(pdev, &size);
 
-       index = 0;
-       if (is_quattro_p(pdev))
-               index = PCI_SLOT(pdev->devfn);
-
-       if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
-               if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
-                       goto use_random;
-       }
+       if (p) {
+               int index = 0;
+               int found;
 
-       pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_reg_orig);
-       pci_write_config_dword(pdev, pdev->rom_base_reg,
-                              rom_reg_orig | PCI_ROM_ADDRESS_ENABLE);
+               if (is_quattro_p(pdev))
+                       index = PCI_SLOT(pdev->devfn);
 
-       p = ioremap(pci_resource_start(pdev, PCI_ROM_RESOURCE), (64 * 1024));
-       if (p != NULL && readb(p) == 0x55 && readb(p + 1) == 0xaa)
-               find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
-
-       if (p != NULL)
-               iounmap(p);
-
-       pci_write_config_dword(pdev, pdev->rom_base_reg, rom_reg_orig);
-       return;
+               found = readb(p) == 0x55 &&
+                       readb(p + 1) == 0xaa &&
+                       find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
+               pci_unmap_rom(pdev, p);
+               if (found)
+                       return;
+       }
 
-use_random:
        /* Sun MAC prefix then 3 random bytes. */
        dev_addr[0] = 0x08;
        dev_addr[1] = 0x00;
index 93800c126e8669c88942fce107a79d775e777fa8..ee48bfd6734938a0e241170e320b1335ee6dac7c 100644 (file)
@@ -2144,9 +2144,9 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
     u_long iobase = 0;                     /* Clear upper 32 bits in Alphas */
     int i, j, cfrv;
     struct de4x5_private *lp = netdev_priv(dev);
-    struct list_head *walk = &pdev->bus_list;
+    struct list_head *walk;
 
-    for (walk = walk->next; walk != &pdev->bus_list; walk = walk->next) {
+    list_for_each(walk, &pdev->bus_list) {
        struct pci_dev *this_dev = pci_dev_b(walk);
 
        /* Skip the pci_bus list entry */
index 91df0bf181ddf7b6d3e9d889af3e7d2714b1ba22..7a57c1b8373f04438a996f05242c8070651c481b 100644 (file)
@@ -215,7 +215,7 @@ static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 va
 #define IOSAPIC_IRDT_ID_EID_SHIFT              0x10
 
 
-static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(iosapic_lock);
 
 static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
 {
index 731855053392995fa6ad4530314ed588b9249056..cb84a4e84a2fd5a3e9aee87e75c3692066645e5d 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/pm.h>
-#include <linux/slab.h>
 #include <linux/types.h>
 
 #include <asm/io.h>
index 694bae162fed916b712112d4feda495e583bcda8..5b887ba5aaf9e613c39939afd62c6f82febef660 100644 (file)
@@ -196,7 +196,7 @@ int parport_wait_peripheral(struct parport *port,
                return 1;
 
        /* 40ms of slow polling. */
-       deadline = jiffies + (HZ + 24) / 25;
+       deadline = jiffies + msecs_to_jiffies(40);
        while (time_before (jiffies, deadline)) {
                int ret;
 
@@ -205,7 +205,7 @@ int parport_wait_peripheral(struct parport *port,
 
                /* Wait for 10ms (or until an interrupt occurs if
                 * the handler is set) */
-               if ((ret = parport_wait_event (port, (HZ + 99) / 100)) < 0)
+               if ((ret = parport_wait_event (port, msecs_to_jiffies(10))) < 0)
                        return ret;
 
                status = parport_read_status (port);
@@ -216,8 +216,7 @@ int parport_wait_peripheral(struct parport *port,
                        /* parport_wait_event didn't time out, but the
                         * peripheral wasn't actually ready either.
                         * Wait for another 10ms. */
-                       __set_current_state (TASK_INTERRUPTIBLE);
-                       schedule_timeout ((HZ+ 99) / 100);
+                       schedule_timeout_interruptible(msecs_to_jiffies(10));
                }
        }
 
index 6624278c6ed86e494d04f53345b1154fcb1c7c79..ce1e2aad8b1008f1efa750fd0155719b4fa8aef4 100644 (file)
@@ -60,7 +60,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
        parport_data_forward (port);
        while (count < len) {
                unsigned long expire = jiffies + dev->timeout;
-               long wait = (HZ + 99) / 100;
+               long wait = msecs_to_jiffies(10);
                unsigned char mask = (PARPORT_STATUS_ERROR
                                      | PARPORT_STATUS_BUSY);
                unsigned char val = (PARPORT_STATUS_ERROR
@@ -97,8 +97,7 @@ size_t parport_ieee1284_write_compat (struct parport *port,
                            our interrupt handler called. */
                        if (count && no_irq) {
                                parport_release (dev);
-                               __set_current_state (TASK_INTERRUPTIBLE);
-                               schedule_timeout (wait);
+                               schedule_timeout_interruptible(wait);
                                parport_claim_or_block (dev);
                        }
                        else
@@ -542,13 +541,12 @@ size_t parport_ieee1284_ecp_read_data (struct parport *port,
                        /* Yield the port for a while. */
                        if (count && dev->port->irq != PARPORT_IRQ_NONE) {
                                parport_release (dev);
-                               __set_current_state (TASK_INTERRUPTIBLE);
-                               schedule_timeout ((HZ + 24) / 25);
+                               schedule_timeout_interruptible(msecs_to_jiffies(40));
                                parport_claim_or_block (dev);
                        }
                        else
                                /* We must have the device claimed here. */
-                               parport_wait_event (port, (HZ + 24) / 25);
+                               parport_wait_event (port, msecs_to_jiffies(40));
 
                        /* Is there a signal pending? */
                        if (signal_pending (current))
index 1b938bb9be3cc0a985c8b22d80fbdac97344e33a..c6493ad7c0c86d070a79e3a4da4754432ef58b62 100644 (file)
@@ -173,8 +173,7 @@ static int change_mode(struct parport *p, int m)
                                if (time_after_eq (jiffies, expire))
                                        /* The FIFO is stuck. */
                                        return -EBUSY;
-                               __set_current_state (TASK_INTERRUPTIBLE);
-                               schedule_timeout ((HZ + 99) / 100);
+                               schedule_timeout_interruptible(msecs_to_jiffies(10));
                                if (signal_pending (current))
                                        break;
                        }
index b844bc97232444ee9dcb6ed5f1b4e06aa75280a2..10444988a10b58532dd942a0af906594904bd5fe 100644 (file)
@@ -20,46 +20,35 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
 
        scratch = buffer;
 
-       /* stuff we want to pass to /sbin/hotplug */
-       envp[i++] = scratch;
-       length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X",
-                           pdev->class);
-       if ((buffer_size - length <= 0) || (i >= num_envp))
+
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "PCI_CLASS=%04X", pdev->class))
                return -ENOMEM;
-       ++length;
-       scratch += length;
 
-       envp[i++] = scratch;
-       length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X",
-                           pdev->vendor, pdev->device);
-       if ((buffer_size - length <= 0) || (i >= num_envp))
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
                return -ENOMEM;
-       ++length;
-       scratch += length;
 
-       envp[i++] = scratch;
-       length += scnprintf (scratch, buffer_size - length,
-                           "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
-                           pdev->subsystem_device);
-       if ((buffer_size - length <= 0) || (i >= num_envp))
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+                               pdev->subsystem_device))
                return -ENOMEM;
-       ++length;
-       scratch += length;
 
-       envp[i++] = scratch;
-       length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s",
-                           pci_name(pdev));
-       if ((buffer_size - length <= 0) || (i >= num_envp))
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "PCI_SLOT_NAME=%s", pci_name(pdev)))
                return -ENOMEM;
 
-       envp[i++] = scratch;
-       length += scnprintf (scratch, buffer_size - length,
-                           "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
-                           pdev->vendor, pdev->device,
-                           pdev->subsystem_vendor, pdev->subsystem_device,
-                           (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
-                           (u8)(pdev->class));
-       if ((buffer_size - length <= 0) || (i >= num_envp))
+       if (add_hotplug_env_var(envp, num_envp, &i,
+                               buffer, buffer_size, &length,
+                               "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
+                               pdev->vendor, pdev->device,
+                               pdev->subsystem_vendor, pdev->subsystem_device,
+                               (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+                               (u8)(pdev->class)))
                return -ENOMEM;
 
        envp[i] = NULL;
index 305b47ec2f2cde3a8d796a0860b8793bce29f446..1406db35b08967f40bfb1c03625a412c68b98263 100644 (file)
@@ -1696,15 +1696,15 @@ void pciehprm_enable_card(
        pci_bus->number = func->bus;
        devfn = PCI_DEVFN(func->device, func->function);
 
-       rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
+       rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd);
 
        if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-               rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
+               rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd);
        }
 
-       cmd = command  = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
+       command  = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
                | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-       bcmd = bcommand  = bcommand | PCI_BRIDGE_CTL_NO_ISA;
+       bcommand  = bcmd | PCI_BRIDGE_CTL_NO_ISA;
 
        ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
        if (ab) {
index cc9d65388e623ffb3436904c16e13cda81204216..56a3b397efee217736b1ce54d6f7621619cb04f4 100644 (file)
@@ -44,10 +44,14 @@ pci_config_attr(subsystem_device, "0x%04x\n");
 pci_config_attr(class, "0x%06x\n");
 pci_config_attr(irq, "%u\n");
 
-static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t local_cpus_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
 {              
-       cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
-       int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
+       cpumask_t mask;
+       int len;
+
+       mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+       len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
        strcat(buf,"\n"); 
        return 1+len;
 }
index d00168b1f66286f8f897a0f19ea0c44e977e5361..d3f3dd42240d79b52c0fdecf5e95333f17131246 100644 (file)
@@ -29,7 +29,6 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
 #endif
 
 /* Functions for PCI Hotplug drivers to use */
-extern struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
 extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
 extern int pci_remove_device_safe(struct pci_dev *dev);
 extern unsigned char pci_max_busnr(void);
index b9c9b03919d449ff967f7359bbd6049fe15c0dc4..26a55d08b506afde854a79dc4bfebd4e57c1ed6a 100644 (file)
@@ -72,11 +72,13 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
 /*
  * PCI Bus Class Devices
  */
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf)
+static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+                                       char *buf)
 {
-       cpumask_t cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
        int ret;
+       cpumask_t cpumask;
 
+       cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
        ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
        if (ret < PAGE_SIZE)
                buf[ret++] = '\n';
@@ -753,27 +755,19 @@ pci_scan_device(struct pci_bus *bus, int devfn)
                kfree(dev);
                return NULL;
        }
-       device_initialize(&dev->dev);
-       dev->dev.release = pci_release_dev;
-       pci_dev_get(dev);
-
-       dev->dev.dma_mask = &dev->dma_mask;
-       dev->dev.coherent_dma_mask = 0xffffffffull;
 
        return dev;
 }
 
-struct pci_dev * __devinit
-pci_scan_single_device(struct pci_bus *bus, int devfn)
+void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
-       struct pci_dev *dev;
+       device_initialize(&dev->dev);
+       dev->dev.release = pci_release_dev;
+       pci_dev_get(dev);
 
-       dev = pci_scan_device(bus, devfn);
-       pci_scan_msi_device(dev);
+       dev->dev.dma_mask = &dev->dma_mask;
+       dev->dev.coherent_dma_mask = 0xffffffffull;
 
-       if (!dev)
-               return NULL;
-       
        /* Fix up broken headers */
        pci_fixup_device(pci_fixup_header, dev);
 
@@ -785,6 +779,19 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
        spin_lock(&pci_bus_lock);
        list_add_tail(&dev->bus_list, &bus->devices);
        spin_unlock(&pci_bus_lock);
+}
+
+struct pci_dev * __devinit
+pci_scan_single_device(struct pci_bus *bus, int devfn)
+{
+       struct pci_dev *dev;
+
+       dev = pci_scan_device(bus, devfn);
+       if (!dev)
+               return NULL;
+
+       pci_device_add(dev, bus);
+       pci_scan_msi_device(dev);
 
        return dev;
 }
@@ -881,7 +888,8 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
        return max;
 }
 
-struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus * __devinit pci_create_bus(struct device *parent,
+               int bus, struct pci_ops *ops, void *sysdata)
 {
        int error;
        struct pci_bus *b;
@@ -938,8 +946,6 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
        b->resource[0] = &ioport_resource;
        b->resource[1] = &iomem_resource;
 
-       b->subordinate = pci_scan_child_bus(b);
-
        return b;
 
 sys_create_link_err:
@@ -957,6 +963,18 @@ err_out:
        kfree(b);
        return NULL;
 }
+EXPORT_SYMBOL_GPL(pci_create_bus);
+
+struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
+               int bus, struct pci_ops *ops, void *sysdata)
+{
+       struct pci_bus *b;
+
+       b = pci_create_bus(parent, bus, ops, sysdata);
+       if (b)
+               b->subordinate = pci_scan_child_bus(b);
+       return b;
+}
 EXPORT_SYMBOL(pci_scan_bus_parented);
 
 #ifdef CONFIG_HOTPLUG
index 4f0c1bd3674a6cf681a992b1f095eba5a5395de2..11ca44387cb03f043eba5ce6f2dcbd35672a68aa 100644 (file)
@@ -876,6 +876,12 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
                        case 0xC00C: /* Samsung P35 notebook */
                                asus_hides_smbus = 1;
                        }
+       } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ)) {
+               if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
+                       switch(dev->subsystem_device) {
+                       case 0x0058: /* Compaq Evo N620c */
+                               asus_hides_smbus = 1;
+                       }
        }
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82845_HB,   asus_hides_smbus_hostbridge );
index 6b0e6464eb391130d1751be13620ae38fd7d5635..657be948baf71fa38d494b957e7e375153192340 100644 (file)
@@ -77,8 +77,7 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
        }
 }
 
-static void __devinit
-pci_setup_cardbus(struct pci_bus *bus)
+void pci_setup_cardbus(struct pci_bus *bus)
 {
        struct pci_dev *bridge = bus->self;
        struct pci_bus_region region;
@@ -130,6 +129,7 @@ pci_setup_cardbus(struct pci_bus *bus)
                                        region.end);
        }
 }
+EXPORT_SYMBOL(pci_setup_cardbus);
 
 /* Initialize bridges with base/limit values we have collected.
    PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
index 6485f75d2fb3beff9d80880ab354c57a5d3dde42..ddc741e6ecbff04b1272817df92e2683fc0f2b09 100644 (file)
@@ -221,6 +221,13 @@ config PCMCIA_VRC4173
        tristate "NEC VRC4173 CARDU support"
        depends on CPU_VR41XX && PCI && PCMCIA
 
+config OMAP_CF
+       tristate "OMAP CompactFlash Controller"
+       depends on PCMCIA && ARCH_OMAP16XX
+       help
+         Say Y here to support the CompactFlash controller on OMAP.
+         Note that this doesn't support "True IDE" mode.
+
 config PCCARD_NONSTATIC
        tristate
 
index ef694c74dfb7ee683938c03df73bc0cbfcae1f86..a41fbb38fdcbe6dfdd145fa0fd72db3ce330c534 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_M32R_CFC)                                += m32r_cfc.o
 obj-$(CONFIG_PCMCIA_AU1X00)                    += au1x00_ss.o
 obj-$(CONFIG_PCMCIA_VRC4171)                   += vrc4171_card.o
 obj-$(CONFIG_PCMCIA_VRC4173)                   += vrc4173_cardu.o
+obj-$(CONFIG_OMAP_CF)                          += omap_cf.o
 
 sa11xx_core-y                                  += soc_common.o sa11xx_base.o
 pxa2xx_core-y                                  += soc_common.o pxa2xx_base.o
index e39178fc59d08efb74efe4eaf1e8ba80a6fbdace..fabd3529cebcb035e56769354986c99e561ecb08 100644 (file)
@@ -654,9 +654,10 @@ static int pccardd(void *__skt)
                skt->thread = NULL;
                complete_and_exit(&skt->thread_done, 0);
        }
-       complete(&skt->thread_done);
 
        add_wait_queue(&skt->thread_wait, &wait);
+       complete(&skt->thread_done);
+
        for (;;) {
                unsigned long flags;
                unsigned int events;
@@ -682,11 +683,11 @@ static int pccardd(void *__skt)
                        continue;
                }
 
-               schedule();
-               try_to_freeze();
-
                if (!skt->thread)
                        break;
+
+               schedule();
+               try_to_freeze();
        }
        remove_wait_queue(&skt->thread_wait, &wait);
 
index 6bbfbd0e02a5d0f834f5b037f6b5a71815992bc4..55867bc7f199664eb4c9eb97dea3fcd13ae3dec6 100644 (file)
@@ -17,9 +17,6 @@
 
 #include <linux/config.h>
 
-#define CLIENT_MAGIC   0x51E6
-typedef struct client_t client_t;
-
 /* Flags in client state */
 #define CLIENT_CONFIG_LOCKED   0x0001
 #define CLIENT_IRQ_REQ         0x0002
@@ -45,7 +42,6 @@ typedef struct region_t {
 typedef struct config_t {
     u_int              state;
     u_int              Attributes;
-    u_int              Vcc, Vpp1, Vpp2;
     u_int              IntType;
     u_int              ConfigBase;
     u_char             Status, Pin, Copy, Option, ExtStatus;
index 43da2e92d50fe67fd633021de9abef67b130bc51..080608c7381a749226fb9d136dbd39f19ec7a380 100644 (file)
@@ -354,6 +354,7 @@ static void pcmcia_release_dev(struct device *dev)
        struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
        ds_dbg(1, "releasing dev %p\n", p_dev);
        pcmcia_put_socket(p_dev->socket);
+       kfree(p_dev->devname);
        kfree(p_dev);
 }
 
@@ -424,9 +425,13 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
 {
        cistpl_manfid_t manf_id;
        cistpl_funcid_t func_id;
-       cistpl_vers_1_t vers1;
+       cistpl_vers_1_t *vers1;
        unsigned int i;
 
+       vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
+       if (!vers1)
+               return -ENOMEM;
+
        if (!pccard_read_tuple(p_dev->socket, p_dev->func,
                               CISTPL_MANFID, &manf_id)) {
                p_dev->manf_id = manf_id.manf;
@@ -443,23 +448,30 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
                /* rule of thumb: cards with no FUNCID, but with
                 * common memory device geometry information, are
                 * probably memory cards (from pcmcia-cs) */
-               cistpl_device_geo_t devgeo;
+               cistpl_device_geo_t *devgeo;
+
+               devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL);
+               if (!devgeo) {
+                       kfree(vers1);
+                       return -ENOMEM;
+               }
                if (!pccard_read_tuple(p_dev->socket, p_dev->func,
-                                     CISTPL_DEVICE_GEO, &devgeo)) {
+                                     CISTPL_DEVICE_GEO, devgeo)) {
                        ds_dbg(0, "mem device geometry probably means "
                               "FUNCID_MEMORY\n");
                        p_dev->func_id = CISTPL_FUNCID_MEMORY;
                        p_dev->has_func_id = 1;
                }
+               kfree(devgeo);
        }
 
        if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
-                              &vers1)) {
-               for (i=0; i < vers1.ns; i++) {
+                              vers1)) {
+               for (i=0; i < vers1->ns; i++) {
                        char *tmp;
                        unsigned int length;
 
-                       tmp = vers1.str + vers1.ofs[i];
+                       tmp = vers1->str + vers1->ofs[i];
 
                        length = strlen(tmp) + 1;
                        if ((length < 3) || (length > 255))
@@ -475,6 +487,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
                }
        }
 
+       kfree(vers1);
        return 0;
 }
 
@@ -492,6 +505,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
 {
        struct pcmcia_device *p_dev;
        unsigned long flags;
+       int bus_id_len;
 
        s = pcmcia_get_socket(s);
        if (!s)
@@ -515,7 +529,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        p_dev->dev.bus = &pcmcia_bus_type;
        p_dev->dev.parent = s->dev.dev;
        p_dev->dev.release = pcmcia_release_dev;
-       sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+       bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+
+       p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
+       if (!p_dev->devname)
+               goto err_free;
+       sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
 
        /* compat */
        p_dev->state = CLIENT_UNBOUND;
@@ -540,6 +559,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        return p_dev;
 
  err_free:
+       kfree(p_dev->devname);
        kfree(p_dev);
        s->device_count--;
  err_put:
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
new file mode 100644 (file)
index 0000000..08d1c92
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * omap_cf.c -- OMAP 16xx CompactFlash controller driver
+ *
+ * Copyright (c) 2005 David Brownell
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/sizes.h>
+
+#include <asm/arch/mux.h>
+#include <asm/arch/tc.h>
+
+
+/* NOTE:  don't expect this to support many I/O cards.  The 16xx chips have
+ * hard-wired timings to support Compact Flash memory cards; they won't work
+ * with various other devices (like WLAN adapters) without some external
+ * logic to help out.
+ *
+ * NOTE:  CF controller docs disagree with address space docs as to where
+ * CF_BASE really lives; this is a doc erratum.
+ */
+#define        CF_BASE 0xfffe2800
+
+/* status; read after IRQ */
+#define CF_STATUS_REG          __REG16(CF_BASE + 0x00)
+#      define  CF_STATUS_BAD_READ      (1 << 2)
+#      define  CF_STATUS_BAD_WRITE     (1 << 1)
+#      define  CF_STATUS_CARD_DETECT   (1 << 0)
+
+/* which chipselect (CS0..CS3) is used for CF (active low) */
+#define CF_CFG_REG             __REG16(CF_BASE + 0x02)
+
+/* card reset */
+#define CF_CONTROL_REG         __REG16(CF_BASE + 0x04)
+#      define  CF_CONTROL_RESET        (1 << 0)
+
+#define omap_cf_present() (!(CF_STATUS_REG & CF_STATUS_CARD_DETECT))
+
+/*--------------------------------------------------------------------------*/
+
+static const char driver_name[] = "omap_cf";
+
+struct omap_cf_socket {
+       struct pcmcia_socket    socket;
+
+       struct timer_list       timer;
+       unsigned                present:1;
+       unsigned                active:1;
+
+       struct platform_device  *pdev;
+       unsigned long           phys_cf;
+       u_int                   irq;
+};
+
+#define        POLL_INTERVAL           (2 * HZ)
+
+#define        SZ_2K                   (2 * SZ_1K)
+
+/*--------------------------------------------------------------------------*/
+
+static int omap_cf_ss_init(struct pcmcia_socket *s)
+{
+       return 0;
+}
+
+/* the timer is primarily to kick this socket's pccardd */
+static void omap_cf_timer(unsigned long _cf)
+{
+       struct omap_cf_socket   *cf = (void *) _cf;
+       unsigned                present = omap_cf_present();
+
+       if (present != cf->present) {
+               cf->present = present;
+               pr_debug("%s: card %s\n", driver_name,
+                       present ? "present" : "gone");
+               pcmcia_parse_events(&cf->socket, SS_DETECT);
+       }
+
+       if (cf->active)
+               mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+}
+
+/* This irq handler prevents "irqNNN: nobody cared" messages as drivers
+ * claim the card's IRQ.  It may also detect some card insertions, but
+ * not removals; it can't always eliminate timer irqs.
+ */
+static irqreturn_t omap_cf_irq(int irq, void *_cf, struct pt_regs *r)
+{
+       omap_cf_timer((unsigned long)_cf);
+       return IRQ_HANDLED;
+}
+
+static int omap_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+{
+       if (!sp)
+               return -EINVAL;
+
+       /* FIXME power management should probably be board-specific:
+        *  - 3VCARD vs XVCARD (OSK only handles 3VCARD)
+        *  - POWERON (switched on/off by set_socket)
+        */
+       if (omap_cf_present()) {
+               struct omap_cf_socket   *cf;
+
+               *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
+               cf = container_of(s, struct omap_cf_socket, socket);
+               s->irq.AssignedIRQ = cf->irq;
+       } else
+               *sp = 0;
+       return 0;
+}
+
+static int
+omap_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+{
+       u16             control;
+
+       /* FIXME some non-OSK boards will support power switching */
+       switch (s->Vcc) {
+       case 0:
+       case 33:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       control = CF_CONTROL_REG;
+       if (s->flags & SS_RESET)
+               CF_CONTROL_REG = CF_CONTROL_RESET;
+       else
+               CF_CONTROL_REG = 0;
+
+       pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+               driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+
+       return 0;
+}
+
+static int omap_cf_ss_suspend(struct pcmcia_socket *s)
+{
+       pr_debug("%s: %s\n", driver_name, __FUNCTION__);
+       return omap_cf_set_socket(s, &dead_socket);
+}
+
+/* regions are 2K each:  mem, attrib, io (and reserved-for-ide) */
+
+static int
+omap_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
+{
+       struct omap_cf_socket   *cf;
+
+       cf = container_of(s, struct omap_cf_socket, socket);
+       io->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+       io->start = cf->phys_cf + SZ_4K;
+       io->stop = io->start + SZ_2K - 1;
+       return 0;
+}
+
+static int
+omap_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+{
+       struct omap_cf_socket   *cf;
+
+       if (map->card_start)
+               return -EINVAL;
+       cf = container_of(s, struct omap_cf_socket, socket);
+       map->static_start = cf->phys_cf;
+       map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
+       if (map->flags & MAP_ATTRIB)
+               map->static_start += SZ_2K;
+       return 0;
+}
+
+static struct pccard_operations omap_cf_ops = {
+       .init                   = omap_cf_ss_init,
+       .suspend                = omap_cf_ss_suspend,
+       .get_status             = omap_cf_get_status,
+       .set_socket             = omap_cf_set_socket,
+       .set_io_map             = omap_cf_set_io_map,
+       .set_mem_map            = omap_cf_set_mem_map,
+};
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * NOTE:  right now the only board-specific platform_data is
+ * "what chipselect is used".  Boards could want more.
+ */
+
+static int __init omap_cf_probe(struct device *dev)
+{
+       unsigned                seg;
+       struct omap_cf_socket   *cf;
+       struct platform_device  *pdev = to_platform_device(dev);
+       int                     irq;
+       int                     status;
+
+       seg = (int) dev->platform_data;
+       if (seg == 0 || seg > 3)
+               return -ENODEV;
+
+       /* either CFLASH.IREQ (INT_1610_CF) or some GPIO */
+       irq = platform_get_irq(pdev, 0);
+       if (!irq)
+               return -EINVAL;
+
+       cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
+       if (!cf)
+               return -ENOMEM;
+       init_timer(&cf->timer);
+       cf->timer.function = omap_cf_timer;
+       cf->timer.data = (unsigned long) cf;
+
+       cf->pdev = pdev;
+       dev_set_drvdata(dev, cf);
+
+       /* this primarily just shuts up irq handling noise */
+       status = request_irq(irq, omap_cf_irq, SA_SHIRQ,
+                       driver_name, cf);
+       if (status < 0)
+               goto fail0;
+       cf->irq = irq;
+       cf->socket.pci_irq = irq;
+
+       switch (seg) {
+       /* NOTE: CS0 could be configured too ... */
+       case 1:
+               cf->phys_cf = OMAP_CS1_PHYS;
+               break;
+       case 2:
+               cf->phys_cf = OMAP_CS2_PHYS;
+               break;
+       case 3:
+               cf->phys_cf = omap_cs3_phys();
+               break;
+       default:
+               goto  fail1;
+       }
+
+       /* pcmcia layer only remaps "real" memory */
+       cf->socket.io_offset = (unsigned long)
+                       ioremap(cf->phys_cf + SZ_4K, SZ_2K);
+       if (!cf->socket.io_offset)
+               goto fail1;
+
+       if (!request_mem_region(cf->phys_cf, SZ_8K, driver_name))
+               goto fail1;
+
+       /* NOTE:  CF conflicts with MMC1 */
+       omap_cfg_reg(W11_1610_CF_CD1);
+       omap_cfg_reg(P11_1610_CF_CD2);
+       omap_cfg_reg(R11_1610_CF_IOIS16);
+       omap_cfg_reg(V10_1610_CF_IREQ);
+       omap_cfg_reg(W10_1610_CF_RESET);
+
+       CF_CFG_REG = ~(1 << seg);
+
+       pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq);
+
+       /* NOTE:  better EMIFS setup might support more cards; but the
+        * TRM only shows how to affect regular flash signals, not their
+        * CF/PCMCIA variants...
+        */
+       pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name,
+                       seg, EMIFS_CCS(seg), EMIFS_ACS(seg));
+       EMIFS_CCS(seg) = 0x0004a1b3;    /* synch mode 4 etc */
+       EMIFS_ACS(seg) = 0x00000000;    /* OE hold/setup */
+
+       /* CF uses armxor_ck, which is "always" available */
+
+       pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name,
+               CF_STATUS_REG, CF_CFG_REG, CF_CONTROL_REG,
+               omap_cf_present() ? "present" : "(not present)");
+
+       cf->socket.owner = THIS_MODULE;
+       cf->socket.dev.dev = dev;
+       cf->socket.ops = &omap_cf_ops;
+       cf->socket.resource_ops = &pccard_static_ops;
+       cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
+                               | SS_CAP_MEM_ALIGN;
+       cf->socket.map_size = SZ_2K;
+
+       status = pcmcia_register_socket(&cf->socket);
+       if (status < 0)
+               goto fail2;
+
+       cf->active = 1;
+       mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
+       return 0;
+
+fail2:
+       iounmap((void __iomem *) cf->socket.io_offset);
+       release_mem_region(cf->phys_cf, SZ_8K);
+fail1:
+       free_irq(irq, cf);
+fail0:
+       kfree(cf);
+       return status;
+}
+
+static int __devexit omap_cf_remove(struct device *dev)
+{
+       struct omap_cf_socket *cf = dev_get_drvdata(dev);
+
+       cf->active = 0;
+       pcmcia_unregister_socket(&cf->socket);
+       del_timer_sync(&cf->timer);
+       iounmap((void __iomem *) cf->socket.io_offset);
+       release_mem_region(cf->phys_cf, SZ_8K);
+       free_irq(cf->irq, cf);
+       kfree(cf);
+       return 0;
+}
+
+static int omap_cf_suspend(struct device *dev, pm_message_t mesg, u32 level)
+{
+       if (level != SUSPEND_SAVE_STATE)
+               return 0;
+       return pcmcia_socket_dev_suspend(dev, mesg);
+}
+
+static int omap_cf_resume(struct device *dev, u32 level)
+{
+       if (level != RESUME_RESTORE_STATE)
+               return 0;
+       return pcmcia_socket_dev_resume(dev);
+}
+
+static struct device_driver omap_cf_driver = {
+       .name           = (char *) driver_name,
+       .bus            = &platform_bus_type,
+       .probe          = omap_cf_probe,
+       .remove         = __devexit_p(omap_cf_remove),
+       .suspend        = omap_cf_suspend,
+       .resume         = omap_cf_resume,
+};
+
+static int __init omap_cf_init(void)
+{
+       if (cpu_is_omap16xx())
+               driver_register(&omap_cf_driver);
+       return 0;
+}
+
+static void __exit omap_cf_exit(void)
+{
+       if (cpu_is_omap16xx())
+               driver_unregister(&omap_cf_driver);
+}
+
+module_init(omap_cf_init);
+module_exit(omap_cf_exit);
+
+MODULE_DESCRIPTION("OMAP CF Driver");
+MODULE_LICENSE("GPL");
index 599b116d9747211514a6522625e6830756f0d492..89022ad5b5207eeac9b90898478f8e49b4088174 100644 (file)
@@ -447,7 +447,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
            (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
                if (mod->Vpp1 != mod->Vpp2)
                        return CS_BAD_VPP;
-               c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
+               s->socket.Vpp = mod->Vpp1;
                if (s->ops->set_socket(s, &s->socket))
                        return CS_BAD_VPP;
        } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
@@ -623,8 +623,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
        if (s->ops->set_socket(s, &s->socket))
                return CS_BAD_VPP;
 
-       c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
-
        /* Pick memory or I/O card, DMA mode, interrupt */
        c->IntType = req->IntType;
        c->Attributes = req->Attributes;
@@ -822,7 +820,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
                                          ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
                                           (s->functions > 1) ||
                                           (irq == s->pci_irq)) ? SA_SHIRQ : 0,
-                                         p_dev->dev.bus_id,
+                                         p_dev->devname,
                                          (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
                        if (!ret) {
                                if (!(req->Attributes & IRQ_HANDLE_PRESENT))
@@ -832,7 +830,8 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
                }
        }
 #endif
-       if (ret) {
+       /* only assign PCI irq if no IRQ already assigned */
+       if (ret && !s->irq.AssignedIRQ) {
                if (!s->pci_irq)
                        return ret;
                irq = s->pci_irq;
@@ -843,7 +842,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
                                ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
                                 (s->functions > 1) ||
                                 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
-                               p_dev->dev.bus_id, req->Instance))
+                               p_dev->devname, req->Instance))
                        return CS_IN_USE;
        }
 
index 0347a29f297bea94f55df5f1ecc3db6795bb648f..f0997c36c9b714b9aaf3a675c6cfb27b96616cdd 100644 (file)
@@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)
 {
        debug("%p %04x %08x\n", socket, reg, val);
        writel(val, socket->base + reg);
+       readl(socket->base + reg); /* avoid problems with PCI write posting */
 }
 
 static inline u8 config_readb(struct yenta_socket *socket, unsigned offset)
@@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val
 {
        debug("%p %04x %02x\n", socket, reg, val);
        writeb(val, socket->base + 0x800 + reg);
+       readb(socket->base + 0x800 + reg); /* PCI write posting... */
 }
 
 static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
@@ -143,6 +145,10 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)
        debug("%p %04x %04x\n", socket, reg, val);
        writeb(val, socket->base + 0x800 + reg);
        writeb(val >> 8, socket->base + 0x800 + reg + 1);
+
+       /* PCI write posting... */
+       readb(socket->base + 0x800 + reg);
+       readb(socket->base + 0x800 + reg + 1);
 }
 
 /*
@@ -667,7 +673,7 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,
        return 0;
 }
 
-static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
+static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)
 {
        struct resource *root, *res;
        struct pci_bus_region region;
@@ -676,7 +682,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
        res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
        /* Already allocated? */
        if (res->parent)
-               return;
+               return 0;
 
        /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */
        mask = ~0xfff;
@@ -692,7 +698,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
                pcibios_bus_to_resource(socket->dev, res, &region);
                root = pci_find_parent_resource(socket->dev, res);
                if (root && (request_resource(root, res) == 0))
-                       return;
+                       return 0;
                printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",
                                pci_name(socket->dev), nr);
        }
@@ -700,35 +706,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
        if (type & IORESOURCE_IO) {
                if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||
                    (yenta_search_res(socket, res, BRIDGE_IO_ACC)) ||
-                   (yenta_search_res(socket, res, BRIDGE_IO_MIN))) {
-                       config_writel(socket, addr_start, res->start);
-                       config_writel(socket, addr_end, res->end);
-                       return;
-               }
+                   (yenta_search_res(socket, res, BRIDGE_IO_MIN)))
+                       return 1;
        } else {
                if (type & IORESOURCE_PREFETCH) {
                        if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
                            (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
-                           (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
-                               config_writel(socket, addr_start, res->start);
-                               config_writel(socket, addr_end, res->end);
-                               return;
-                       }
+                           (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+                               return 1;
                        /* Approximating prefetchable by non-prefetchable */
                        res->flags = IORESOURCE_MEM;
                }
                if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||
                    (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) ||
-                   (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) {
-                       config_writel(socket, addr_start, res->start);
-                       config_writel(socket, addr_end, res->end);
-                       return;
-               }
+                   (yenta_search_res(socket, res, BRIDGE_MEM_MIN)))
+                       return 1;
        }
 
        printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",
               pci_name(socket->dev), type);
        res->start = res->end = res->flags = 0;
+       return 0;
 }
 
 /*
@@ -736,14 +734,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ
  */
 static void yenta_allocate_resources(struct yenta_socket *socket)
 {
-       yenta_allocate_res(socket, 0, IORESOURCE_IO,
+       int program = 0;
+       program += yenta_allocate_res(socket, 0, IORESOURCE_IO,
                           PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0);
-       yenta_allocate_res(socket, 1, IORESOURCE_IO,
+       program += yenta_allocate_res(socket, 1, IORESOURCE_IO,
                           PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1);
-       yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
+       program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,
                           PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0);
-       yenta_allocate_res(socket, 3, IORESOURCE_MEM,
+       program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,
                           PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1);
+       if (program)
+               pci_setup_cardbus(socket->dev->subordinate);
 }
 
 
@@ -758,7 +759,7 @@ static void yenta_free_resources(struct yenta_socket *socket)
                res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;
                if (res->start != 0 && res->end != 0)
                        release_resource(res);
-               res->start = res->end = 0;
+               res->start = res->end = res->flags = 0;
        }
 }
 
index d96cc47de5668e203cbb49a4d77c85c2d72c1485..672f9f2b21634e93546592f0ed833706a725d09b 100644 (file)
@@ -871,8 +871,7 @@ static irqreturn_t aurora_interrupt(int irq, void * dev_id, struct pt_regs * reg
 #ifdef AURORA_INT_DEBUG
 static void aurora_timer (unsigned long ignored);
 
-static struct timer_list aurora_poll_timer =
-                       TIMER_INITIALIZER(aurora_timer, 0, 0);
+static DEFINE_TIMER(aurora_poll_timer, aurora_timer, 0, 0);
 
 static void
 aurora_timer (unsigned long ignored)
index d44205d52bf3ce7a69a0da0678c0fe0d377f10d9..d89f83f769f5426d36d3e5ec16a18afcffd61469 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #define __KERNEL_SYSCALLS__
+static int errno;
 
 #include <linux/kernel.h>
 #include <linux/kthread.h>
@@ -13,8 +14,6 @@
 #include <linux/delay.h>
 #include <asm/oplib.h>
 #include <asm/ebus.h>
-static int errno;
-#include <asm/unistd.h>
 
 #include "bbc_i2c.h"
 #include "max1617.h"
index d765cc1bf060bc30d17e1e3ba78d01429dedf457..b0cc3c2588fdd44074cf6ae873c920489b0a111f 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #define __KERNEL_SYSCALLS__
+static int errno;
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -38,9 +39,6 @@
 #include <asm/uaccess.h>
 #include <asm/envctrl.h>
 
-static int errno;
-#include <asm/unistd.h>
-
 #define ENVCTRL_MINOR  162
 
 #define PCF8584_ADDRESS        0x55
index 2341d27ceed7359991733e564eebba5c6a039f08..7a33c708f5b3dd0a65d4433e3900d52f64ae42aa 100644 (file)
@@ -6090,8 +6090,8 @@ NCR53c7x0_release(struct Scsi_Host *host) {
     if (hostdata->num_cmds)
        printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n",
            host->host_no, hostdata->num_cmds);
-    if (hostdata->events) 
-       vfree ((void *)hostdata->events);
+
+    vfree(hostdata->events);
 
     /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
      * XXX may be invalid (CONFIG_060_WRITETHROUGH)
index bd0e1b6be1ea6d50badb9e13c7717de66332e1d3..da6e51c7fe696dd74ed6b688c3ccef48f482df3e 100644 (file)
@@ -116,7 +116,7 @@ typedef struct {
 } scsi_changer;
 
 static LIST_HEAD(ch_devlist);
-static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ch_devlist_lock);
 static int ch_devcount;
 
 static struct scsi_driver ch_template =
@@ -560,7 +560,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
        return result;
 }
 
-static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest)
+static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
 {
        int retval = 0;
        u_char data[16];
@@ -634,6 +634,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
 {
        scsi_changer *ch = file->private_data;
        int retval;
+       void __user *argp = (void __user *)arg;
        
        switch (cmd) {
        case CHIOGPARAMS:
@@ -646,7 +647,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
                params.cp_nportals  = ch->counts[CHET_IE];
                params.cp_ndrives   = ch->counts[CHET_DT];
                
-               if (copy_to_user((void *) arg, &params, sizeof(params)))
+               if (copy_to_user(argp, &params, sizeof(params)))
                        return -EFAULT;
                return 0;
        }
@@ -671,7 +672,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
                        vparams.cvp_n4  = ch->counts[CHET_V4];
                        strncpy(vparams.cvp_label4,vendor_labels[3],16);
                }
-               if (copy_to_user((void *) arg, &vparams, sizeof(vparams)))
+               if (copy_to_user(argp, &vparams, sizeof(vparams)))
                        return -EFAULT;
                return 0;
        }
@@ -680,7 +681,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
        {
                struct changer_position pos;
                
-               if (copy_from_user(&pos, (void*)arg, sizeof (pos)))
+               if (copy_from_user(&pos, argp, sizeof (pos)))
                        return -EFAULT;
 
                if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
@@ -699,7 +700,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
        {
                struct changer_move mv;
 
-               if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+               if (copy_from_user(&mv, argp, sizeof (mv)))
                        return -EFAULT;
 
                if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
@@ -721,7 +722,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
        {
                struct changer_exchange mv;
                
-               if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+               if (copy_from_user(&mv, argp, sizeof (mv)))
                        return -EFAULT;
 
                if (0 != ch_checkrange(ch, mv.ce_srctype,  mv.ce_srcunit ) ||
@@ -746,7 +747,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
        {
                struct changer_element_status ces;
                
-               if (copy_from_user(&ces, (void*)arg, sizeof (ces)))
+               if (copy_from_user(&ces, argp, sizeof (ces)))
                        return -EFAULT;
                if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
                        return -EINVAL;
@@ -762,7 +763,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
                unsigned int elem;
                int     result,i;
                
-               if (copy_from_user(&cge, (void*)arg, sizeof (cge)))
+               if (copy_from_user(&cge, argp, sizeof (cge)))
                        return -EFAULT;
 
                if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
@@ -825,7 +826,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
                kfree(buffer);
                up(&ch->lock);
                
-               if (copy_to_user((void*)arg, &cge, sizeof (cge)))
+               if (copy_to_user(argp, &cge, sizeof (cge)))
                        return -EFAULT;
                return result;
        }
@@ -843,7 +844,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
                struct changer_set_voltag csv;
                int elem;
 
-               if (copy_from_user(&csv, (void*)arg, sizeof(csv)))
+               if (copy_from_user(&csv, argp, sizeof(csv)))
                        return -EFAULT;
 
                if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
@@ -861,7 +862,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
        }
 
        default:
-               return scsi_ioctl(ch->device, cmd, (void*)arg);
+               return scsi_ioctl(ch->device, cmd, argp);
 
        }
 }
@@ -894,9 +895,9 @@ static long ch_ioctl_compat(struct file * file,
        case CHIOGSTATUS32:
        {
                struct changer_element_status32 ces32;
-               unsigned char *data;
+               unsigned char __user *data;
                
-               if (copy_from_user(&ces32, (void*)arg, sizeof (ces32)))
+               if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32)))
                        return -EFAULT;
                if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
                        return -EINVAL;
index d72be0ce89c84534911026dce7879659045bd619..3fda8d455c5b06e1965d95f26810d128586ab690 100644 (file)
@@ -691,8 +691,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg)
         if(  copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
                result = -EFAULT;
 
-        if( buf) 
-         kfree( buf);
+       kfree(buf);
 
         return result;
       }
index b5dc3535557079d368444aa136f1ff28fcdae3ca..6e54c7d9b33c9d1788a26150cf4d2ff2d395b9fc 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/mca.h>
-#include <linux/string.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/mca-legacy.h>
index 89a4a0615c22d67d6099527443347ec3f21f5026..3f2f2464fa6351ebbe8938c594e3f3cce3dec9c1 100644 (file)
@@ -1377,7 +1377,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
        
                if ((STp->buffer)->syscall_result || !SRpnt) {
                        printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
-                       vfree((void *)buffer);
+                       vfree(buffer);
                        *aSRpnt = SRpnt;
                        return (-EIO);
                }
@@ -1419,7 +1419,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
 
                        if (new_frame > frame + 1000) {
                                printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
-                               vfree((void *)buffer);
+                               vfree(buffer);
                                return (-EIO);
                        }
                        if ( i >= nframes + pending ) break;
@@ -1500,7 +1500,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
                             SRpnt->sr_sense_buffer[12]         ==  0 &&
                             SRpnt->sr_sense_buffer[13]         ==  2) {
                                printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
-                               vfree((void *)buffer);
+                               vfree(buffer);
                                return (-EIO);                  /* hit end of tape = fail */
                        }
                        i = ((SRpnt->sr_sense_buffer[3] << 24) |
@@ -1525,7 +1525,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi
        }
        if (!pending)
                osst_copy_to_buffer(STp->buffer, p);    /* so buffer content == at entry in all cases */
-       vfree((void *)buffer);
+       vfree(buffer);
        return 0;
 }
 
@@ -5852,7 +5852,7 @@ static int osst_remove(struct device *dev)
                        os_scsi_tapes[i] = NULL;
                        osst_nr_dev--;
                        write_unlock(&os_scsi_tapes_lock);
-                       if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
+                       vfree(tpnt->header_cache);
                        if (tpnt->buffer) {
                                normalize_buffer(tpnt->buffer);
                                kfree(tpnt->buffer);
@@ -5896,8 +5896,7 @@ static void __exit exit_osst (void)
                for (i=0; i < osst_max_dev; ++i) {
                        if (!(STp = os_scsi_tapes[i])) continue;
                        /* This is defensive, supposed to happen during detach */
-                       if (STp->header_cache)
-                               vfree(STp->header_cache);
+                       vfree(STp->header_cache);
                        if (STp->buffer) {
                                normalize_buffer(STp->buffer);
                                kfree(STp->buffer);
index 623082d3a83f5369d8184be262d9eb1c0404459d..c89da7d5b6dffb49cf9994c7a59540abf8eea5bc 100644 (file)
@@ -95,8 +95,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
        int i, retry, nplutos;
        fc_channel *fc;
        Scsi_Device dev;
-       struct timer_list fc_timer =
-               TIMER_INITIALIZER(pluto_detect_timeout, 0, 0);
+       DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0);
 
        tpnt->proc_name = "pluto";
        fcscount = 0;
index 72bbaa91dc7778c66a2e6da7ad4540097912c9c3..9791496fa78844076de8192e5a907013312715ee 100644 (file)
@@ -1334,7 +1334,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
                WRT_REG_DWORD(dmp_reg, 0xB0200000);
-               dmp_reg = (uint32_t *)((uint8_t *)reg + 0xFC);
+               dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
                fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg);
 
                dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
index 5b65e208893bc80df44179ceb2dd5d6a32b1dccc..4d75cdfa0a0af00bd928faae571008dcbac4d0a2 100644 (file)
@@ -864,7 +864,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
        /*
         * We're pretty sure there's a port here.  Lets find out what
         * type of port it is.  The IIR top two bits allows us to find
-        * out if its 8250 or 16450, 16550, 16550A or later.  This
+        * out if it's 8250 or 16450, 16550, 16550A or later.  This
         * determines what we test for next.
         *
         * We also initialise the EFR (if any) to zero for later.  The
index 43b03c55f453859a2902c7dc50d72f741b508e20..e2ebdcad553c405b012a83c7674fe69472b42a1f 100644 (file)
@@ -63,8 +63,13 @@ struct timer_list mcfrs_timer_struct;
 #endif
 
 #if defined(CONFIG_HW_FEITH)
-  #define      CONSOLE_BAUD_RATE       38400
-  #define      DEFAULT_CBAUD           B38400
+#define        CONSOLE_BAUD_RATE       38400
+#define        DEFAULT_CBAUD           B38400
+#endif
+
+#if defined(CONFIG_MOD5272)
+#define CONSOLE_BAUD_RATE      115200
+#define DEFAULT_CBAUD          B115200
 #endif
 
 #ifndef CONSOLE_BAUD_RATE
@@ -90,7 +95,7 @@ static struct tty_driver *mcfrs_serial_driver;
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
 
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 #define        IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
 #else
 #define        IRQBASE 73
@@ -1510,7 +1515,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
        *portp = (*portp & ~0x000000ff) | 0x00000055;
        portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
        *portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
        volatile unsigned char *icrp, *uartp;
        volatile unsigned long *imrp;
 
index 49afadbe461b2875ad5b6f0c913cf9906551b5f0..f10c86d60b647fb8dedad8423d7f507920d3b705 100644 (file)
@@ -31,6 +31,8 @@
  *     1.01    Set fifosize to make tx_empry called properly.
  *             Use standard uart_get_divisor.
  *     1.02    Cleanup. (import 8250.c changes)
+ *     1.03    Fix low-latency mode. (import 8250.c changes)
+ *     1.04    Remove usage of deprecated functions, cleanup.
  */
 #include <linux/config.h>
 
@@ -54,7 +56,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static char *serial_version = "1.02";
+static char *serial_version = "1.04";
 static char *serial_name = "TX39/49 Serial driver";
 
 #define PASS_LIMIT     256
@@ -86,9 +88,9 @@ static char *serial_name = "TX39/49 Serial driver";
  */
 #ifdef ENABLE_SERIAL_TXX9_PCI
 #define NR_PCI_BOARDS  4
-#define UART_NR  (2 + NR_PCI_BOARDS)
+#define UART_NR  (4 + NR_PCI_BOARDS)
 #else
-#define UART_NR  2
+#define UART_NR  4
 #endif
 
 struct uart_txx9_port {
@@ -304,8 +306,11 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
                /* The following is not allowed by the tty layer and
                   unsafe. It should be fixed ASAP */
                if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
-                       if(tty->low_latency)
+                       if (tty->low_latency) {
+                               spin_unlock(&up->port.lock);
                                tty_flip_buffer_push(tty);
+                               spin_lock(&up->port.lock);
+                       }
                        /* If this failed then we will throw away the
                           bytes but must do so to clear interrupts */
                }
@@ -356,7 +361,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
        ignore_char:
                disr = sio_in(up, TXX9_SIDISR);
        } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
+       spin_unlock(&up->port.lock);
        tty_flip_buffer_push(tty);
+       spin_lock(&up->port.lock);
        *status = disr;
 }
 
@@ -667,17 +674,8 @@ serial_txx9_pm(struct uart_port *port, unsigned int state,
              unsigned int oldstate)
 {
        struct uart_txx9_port *up = (struct uart_txx9_port *)port;
-       if (state) {
-               /* sleep */
-
-               if (up->pm)
-                       up->pm(port, state, oldstate);
-       } else {
-               /* wake */
-
-               if (up->pm)
-                       up->pm(port, state, oldstate);
-       }
+       if (up->pm)
+               up->pm(port, state, oldstate);
 }
 
 static int serial_txx9_request_resource(struct uart_txx9_port *up)
@@ -979,14 +977,6 @@ static int __init serial_txx9_console_init(void)
 }
 console_initcall(serial_txx9_console_init);
 
-static int __init serial_txx9_late_console_init(void)
-{
-       if (!(serial_txx9_console.flags & CON_ENABLED))
-               register_console(&serial_txx9_console);
-       return 0;
-}
-late_initcall(serial_txx9_late_console_init);
-
 #define SERIAL_TXX9_CONSOLE    &serial_txx9_console
 #else
 #define SERIAL_TXX9_CONSOLE    NULL
@@ -1039,6 +1029,73 @@ static void serial_txx9_resume_port(int line)
        uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
 }
 
+static DECLARE_MUTEX(serial_txx9_sem);
+
+/**
+ *     serial_txx9_register_port - register a serial port
+ *     @port: serial port template
+ *
+ *     Configure the serial port specified by the request.
+ *
+ *     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.
+ */
+static int __devinit serial_txx9_register_port(struct uart_port *port)
+{
+       int i;
+       struct uart_txx9_port *uart;
+       int ret = -ENOSPC;
+
+       down(&serial_txx9_sem);
+       for (i = 0; i < UART_NR; i++) {
+               uart = &serial_txx9_ports[i];
+               if (uart->port.type == PORT_UNKNOWN)
+                       break;
+       }
+       if (i < UART_NR) {
+               uart_remove_one_port(&serial_txx9_reg, &uart->port);
+               uart->port.iobase = port->iobase;
+               uart->port.membase = port->membase;
+               uart->port.irq      = port->irq;
+               uart->port.uartclk  = port->uartclk;
+               uart->port.iotype   = port->iotype;
+               uart->port.flags    = port->flags | UPF_BOOT_AUTOCONF;
+               uart->port.mapbase  = port->mapbase;
+               if (port->dev)
+                       uart->port.dev = port->dev;
+               ret = uart_add_one_port(&serial_txx9_reg, &uart->port);
+               if (ret == 0)
+                       ret = uart->port.line;
+       }
+       up(&serial_txx9_sem);
+       return ret;
+}
+
+/**
+ *     serial_txx9_unregister_port - remove a txx9 serial port at runtime
+ *     @line: serial line number
+ *
+ *     Remove one serial port.  This may not be called from interrupt
+ *     context.  We hand the port back to the our control.
+ */
+static void __devexit serial_txx9_unregister_port(int line)
+{
+       struct uart_txx9_port *uart = &serial_txx9_ports[line];
+
+       down(&serial_txx9_sem);
+       uart_remove_one_port(&serial_txx9_reg, &uart->port);
+       uart->port.flags = 0;
+       uart->port.type = PORT_UNKNOWN;
+       uart->port.iobase = 0;
+       uart->port.mapbase = 0;
+       uart->port.membase = 0;
+       uart->port.dev = NULL;
+       uart_add_one_port(&serial_txx9_reg, &uart->port);
+       up(&serial_txx9_sem);
+}
+
 /*
  * Probe one serial board.  Unfortunately, there is no rhyme nor reason
  * to the arrangement of serial ports on a PCI card.
@@ -1056,13 +1113,13 @@ pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 
        memset(&port, 0, sizeof(port));
        port.ops = &serial_txx9_pops;
-       port.flags |= UPF_BOOT_AUTOCONF; /* uart_ops.config_port will be called */
        port.flags |= UPF_TXX9_HAVE_CTS_LINE;
        port.uartclk = 66670000;
        port.irq = dev->irq;
        port.iotype = UPIO_PORT;
        port.iobase = pci_resource_start(dev, 1);
-       line = uart_register_port(&serial_txx9_reg, &port);
+       port.dev = &dev->dev;
+       line = serial_txx9_register_port(&port);
        if (line < 0) {
                printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), line);
        }
@@ -1078,7 +1135,7 @@ static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
        pci_set_drvdata(dev, NULL);
 
        if (line) {
-               uart_unregister_port(&serial_txx9_reg, line);
+               serial_txx9_unregister_port(line);
                pci_disable_device(dev);
        }
 }
@@ -1089,6 +1146,8 @@ static int pciserial_txx9_suspend_one(struct pci_dev *dev, pm_message_t state)
 
        if (line)
                serial_txx9_suspend_port(line);
+       pci_save_state(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
        return 0;
 }
 
@@ -1096,8 +1155,13 @@ static int pciserial_txx9_resume_one(struct pci_dev *dev)
 {
        int line = (int)(long)pci_get_drvdata(dev);
 
-       if (line)
+       pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
+
+       if (line) {
+               pci_enable_device(dev);
                serial_txx9_resume_port(line);
+       }
        return 0;
 }
 
index f2c9fa423d402d1262b6af64e3d3180c567f39cf..f6704688ee8c2e15efb500ce0ed807030e078280 100644 (file)
@@ -774,10 +774,7 @@ static int ixj_wink(IXJ *j)
        j->pots_winkstart = jiffies;
        SLIC_SetState(PLD_SLIC_STATE_OC, j);
 
-       while (time_before(jiffies, j->pots_winkstart + j->winktime)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       msleep(jiffies_to_msecs(j->winktime));
 
        SLIC_SetState(slicnow, j);
        return 0;
@@ -1912,7 +1909,6 @@ static int ixj_pcmcia_cable_check(IXJ *j)
 
 static int ixj_hookstate(IXJ *j)
 {
-       unsigned long det;
        int fOffHook = 0;
 
        switch (j->cardtype) {
@@ -1943,11 +1939,7 @@ static int ixj_hookstate(IXJ *j)
                            j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
                                if (j->flags.ringing || j->flags.cringing) {
                                        if (!in_interrupt()) {
-                                               det = jiffies + (hertz / 50);
-                                               while (time_before(jiffies, det)) {
-                                                       set_current_state(TASK_INTERRUPTIBLE);
-                                                       schedule_timeout(1);
-                                               }
+                                               msleep(20);
                                        }
                                        SLIC_GetState(j);
                                        if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {
@@ -2062,7 +2054,7 @@ static void ixj_ring_start(IXJ *j)
 static int ixj_ring(IXJ *j)
 {
        char cntr;
-       unsigned long jif, det;
+       unsigned long jif;
 
        j->flags.ringing = 1;
        if (ixj_hookstate(j) & 1) {
@@ -2070,7 +2062,6 @@ static int ixj_ring(IXJ *j)
                j->flags.ringing = 0;
                return 1;
        }
-       det = 0;
        for (cntr = 0; cntr < j->maxrings; cntr++) {
                jif = jiffies + (1 * hertz);
                ixj_ring_on(j);
@@ -2080,8 +2071,7 @@ static int ixj_ring(IXJ *j)
                                j->flags.ringing = 0;
                                return 1;
                        }
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
+                       schedule_timeout_interruptible(1);
                        if (signal_pending(current))
                                break;
                }
@@ -2089,20 +2079,13 @@ static int ixj_ring(IXJ *j)
                ixj_ring_off(j);
                while (time_before(jiffies, jif)) {
                        if (ixj_hookstate(j) & 1) {
-                               det = jiffies + (hertz / 100);
-                               while (time_before(jiffies, det)) {
-                                       set_current_state(TASK_INTERRUPTIBLE);
-                                       schedule_timeout(1);
-                                       if (signal_pending(current))
-                                               break;
-                               }
+                               msleep(10);
                                if (ixj_hookstate(j) & 1) {
                                        j->flags.ringing = 0;
                                        return 1;
                                }
                        }
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
+                       schedule_timeout_interruptible(1);
                        if (signal_pending(current))
                                break;
                }
@@ -2168,10 +2151,8 @@ static int ixj_release(struct inode *inode, struct file *file_p)
         *    Set up locks to ensure that only one process is talking to the DSP at a time.
         *    This is necessary to keep the DSP from locking up.
         */
-       while(test_and_set_bit(board, (void *)&j->busyflags) != 0) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
+               schedule_timeout_interruptible(1);
        if (ixjdebug & 0x0002)
                printk(KERN_INFO "Closing board %d\n", NUM(inode));
 
@@ -3301,14 +3282,10 @@ static void ixj_write_cidcw(IXJ *j)
        ixj_play_tone(j, 23);
 
        clear_bit(j->board, &j->busyflags);
-       while(j->tone_state) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
-       while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while(j->tone_state)
+               schedule_timeout_interruptible(1);
+       while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+               schedule_timeout_interruptible(1);
        if(ixjdebug & 0x0200) {
                printk("IXJ cidcw phone%d first tone end at %ld\n", j->board, jiffies);
        }
@@ -3328,14 +3305,10 @@ static void ixj_write_cidcw(IXJ *j)
        ixj_play_tone(j, 24);
 
        clear_bit(j->board, &j->busyflags);
-       while(j->tone_state) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
-       while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while(j->tone_state)
+               schedule_timeout_interruptible(1);
+       while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+               schedule_timeout_interruptible(1);
        if(ixjdebug & 0x0200) {
                printk("IXJ cidcw phone%d sent second tone at %ld\n", j->board, jiffies);
        }
@@ -3343,14 +3316,10 @@ static void ixj_write_cidcw(IXJ *j)
        j->cidcw_wait = jiffies + ((50 * hertz) / 100);
 
        clear_bit(j->board, &j->busyflags);
-       while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
-       while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while(!j->flags.cidcw_ack && time_before(jiffies, j->cidcw_wait))
+               schedule_timeout_interruptible(1);
+       while(test_and_set_bit(j->board, (void *)&j->busyflags) != 0)
+               schedule_timeout_interruptible(1);
        j->cidcw_wait = 0;
        if(!j->flags.cidcw_ack) {
                if(ixjdebug & 0x0200) {
@@ -6125,10 +6094,8 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd,
         *    Set up locks to ensure that only one process is talking to the DSP at a time.
         *    This is necessary to keep the DSP from locking up.
         */
-       while(test_and_set_bit(board, (void *)&j->busyflags) != 0) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       while(test_and_set_bit(board, (void *)&j->busyflags) != 0)
+               schedule_timeout_interruptible(1);
        if (ixjdebug & 0x0040)
                printk("phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
        if (minor >= IXJMAX) {
@@ -6694,8 +6661,6 @@ static struct file_operations ixj_fops =
 
 static int ixj_linetest(IXJ *j)
 {
-       unsigned long jifwait;
-
        j->flags.pstncheck = 1; /* Testing */
        j->flags.pstn_present = 0; /* Assume the line is not there */
 
@@ -6726,11 +6691,7 @@ static int ixj_linetest(IXJ *j)
 
                outb_p(j->pld_scrw.byte, j->XILINXbase);
                daa_set_mode(j, SOP_PU_CONVERSATION);
-               jifwait = jiffies + hertz;
-               while (time_before(jiffies, jifwait)) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(1);
-               }
+               msleep(1000);
                daa_int_read(j);
                daa_set_mode(j, SOP_PU_RESET);
                if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
@@ -6750,11 +6711,7 @@ static int ixj_linetest(IXJ *j)
        j->pld_slicw.bits.rly3 = 0;
        outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
        daa_set_mode(j, SOP_PU_CONVERSATION);
-       jifwait = jiffies + hertz;
-       while (time_before(jiffies, jifwait)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(1);
-       }
+       msleep(1000);
        daa_int_read(j);
        daa_set_mode(j, SOP_PU_RESET);
        if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
@@ -6783,7 +6740,6 @@ static int ixj_linetest(IXJ *j)
 static int ixj_selfprobe(IXJ *j)
 {
        unsigned short cmd;
-       unsigned long jif;
        int cnt;
        BYTES bytes;
 
@@ -6933,29 +6889,13 @@ static int ixj_selfprobe(IXJ *j)
        } else {
                if (j->cardtype == QTI_LINEJACK) {
                        LED_SetState(0x1, j);
-                       jif = jiffies + (hertz / 10);
-                       while (time_before(jiffies, jif)) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       msleep(100);
                        LED_SetState(0x2, j);
-                       jif = jiffies + (hertz / 10);
-                       while (time_before(jiffies, jif)) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       msleep(100);
                        LED_SetState(0x4, j);
-                       jif = jiffies + (hertz / 10);
-                       while (time_before(jiffies, jif)) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       msleep(100);
                        LED_SetState(0x8, j);
-                       jif = jiffies + (hertz / 10);
-                       while (time_before(jiffies, jif)) {
-                               set_current_state(TASK_INTERRUPTIBLE);
-                               schedule_timeout(1);
-                       }
+                       msleep(100);
                        LED_SetState(0x0, j);
                        daa_get_version(j);
                        if (ixjdebug & 0x0002)
index 81f8f6b7fdce1aded2ef2ecbc206422e47fb6434..a8267cf17db4685b34da64dd1c4adec99fb5642c 100644 (file)
@@ -178,8 +178,8 @@ static __u8 root_hub_hub_des[] =
        0xff   /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
 };
 
-static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0);
-static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0);
+static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
 
 /* We want the start timer to expire before the eot timer, because the former might start
    traffic, thus making it unnecessary for the latter to time out. */
index 1ab95d24c5e25c8715078538ff6176b2b4f01883..e108e0a36b743fd88c191a7e96c8339dbe39f451 100644 (file)
@@ -2,7 +2,8 @@
  *  USB HID support for Linux
  *
  *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  */
 
 /*
@@ -38,7 +39,7 @@
  * Version Information
  */
 
-#define DRIVER_VERSION "v2.01"
+#define DRIVER_VERSION "v2.6"
 #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
@@ -1058,8 +1059,8 @@ static int hid_submit_ctrl(struct hid_device *hid)
                if (maxpacket > 0) {
                        padlen = (len + maxpacket - 1) / maxpacket;
                        padlen *= maxpacket;
-                       if (padlen > HID_BUFFER_SIZE)
-                               padlen = HID_BUFFER_SIZE;
+                       if (padlen > hid->bufsize)
+                               padlen = hid->bufsize;
                } else
                        padlen = 0;
                hid->urbctrl->transfer_buffer_length = padlen;
@@ -1096,6 +1097,7 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
 
        switch (urb->status) {
                case 0:                 /* success */
+                       break;
                case -ESHUTDOWN:        /* unplug */
                case -EILSEQ:           /* unplug timeout on uhci */
                        unplug = 1;
@@ -1143,6 +1145,7 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
                case 0:                 /* success */
                        if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
                                hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0, regs);
+                       break;
                case -ESHUTDOWN:        /* unplug */
                case -EILSEQ:           /* unplug timectrl on uhci */
                        unplug = 1;
@@ -1284,13 +1287,8 @@ void hid_init_reports(struct hid_device *hid)
        struct hid_report *report;
        int err, ret;
 
-       list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
-               int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
-               if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
-               if (size > hid->urbin->transfer_buffer_length)
-                       hid->urbin->transfer_buffer_length = size;
+       list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
                hid_submit_report(hid, report, USB_DIR_IN);
-       }
 
        list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
                hid_submit_report(hid, report, USB_DIR_IN);
@@ -1372,12 +1370,14 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_A4TECH           0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU   0x0006
 
-#define USB_VENDOR_ID_AASHIMA          0x06D6
+#define USB_VENDOR_ID_AASHIMA          0x06d6
 #define USB_DEVICE_ID_AASHIMA_GAMEPAD  0x0025
+#define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026
 
 #define USB_VENDOR_ID_CYPRESS          0x04b4
 #define USB_DEVICE_ID_CYPRESS_MOUSE    0x0001
 #define USB_DEVICE_ID_CYPRESS_HIDCOM   0x5500
+#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE       0x7417
 
 #define USB_VENDOR_ID_BERKSHIRE                0x0c98
 #define USB_DEVICE_ID_BERKSHIRE_PCWD   0x1140
@@ -1432,7 +1432,7 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_VERNIER_CYCLOPS  0x0004
 
 #define USB_VENDOR_ID_LD               0x0f11
-#define USB_DEVICE_ID_CASSY            0x1000
+#define USB_DEVICE_ID_CASSY            0x1000
 #define USB_DEVICE_ID_POCKETCASSY      0x1010
 #define USB_DEVICE_ID_MOBILECASSY      0x1020
 #define USB_DEVICE_ID_JWM              0x1080
@@ -1445,7 +1445,8 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_POWERCONTROL     0x2030
 
 #define USB_VENDOR_ID_APPLE            0x05ac
-#define USB_DEVICE_ID_APPLE_BLUETOOTH          0x1000
+#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
+#define USB_DEVICE_ID_APPLE_BLUETOOTH  0x1000
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -1471,6 +1472,7 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
@@ -1551,10 +1553,12 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
        { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
        { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
 
        { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD },
+       { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
        { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -1567,15 +1571,32 @@ static struct hid_blacklist {
        { 0, 0 }
 };
 
+/*
+ * Traverse the supplied list of reports and find the longest
+ */
+static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
+{
+       struct hid_report *report;
+       int size;
+
+       list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
+               size = ((report->size - 1) >> 3) + 1;
+               if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
+                       size++;
+               if (*max < size)
+                       *max = size;
+       }
+}
+
 static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 {
-       if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma)))
+       if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
                return -1;
-       if (!(hid->outbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->outbuf_dma)))
+       if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
                return -1;
        if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
                return -1;
-       if (!(hid->ctrlbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
+       if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
                return -1;
 
        return 0;
@@ -1584,13 +1605,13 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
        if (hid->inbuf)
-               usb_buffer_free(dev, HID_BUFFER_SIZE, hid->inbuf, hid->inbuf_dma);
+               usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
        if (hid->outbuf)
-               usb_buffer_free(dev, HID_BUFFER_SIZE, hid->outbuf, hid->outbuf_dma);
+               usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
        if (hid->cr)
                usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
        if (hid->ctrlbuf)
-               usb_buffer_free(dev, HID_BUFFER_SIZE, hid->ctrlbuf, hid->ctrlbuf_dma);
+               usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
 }
 
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
@@ -1601,7 +1622,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        struct hid_device *hid;
        unsigned quirks = 0, rsize = 0;
        char *buf, *rdesc;
-       int n;
+       int n, insize = 0;
 
        for (n = 0; hid_blacklist[n].idVendor; n++)
                if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
@@ -1655,6 +1676,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        kfree(rdesc);
        hid->quirks = quirks;
 
+       hid->bufsize = HID_MIN_BUFFER_SIZE;
+       hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
+       hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
+       hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+
+       if (hid->bufsize > HID_MAX_BUFFER_SIZE)
+               hid->bufsize = HID_MAX_BUFFER_SIZE;
+
+       hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
+
+       if (insize > HID_MAX_BUFFER_SIZE)
+               insize = HID_MAX_BUFFER_SIZE;
+
        if (hid_alloc_buffers(dev, hid)) {
                hid_free_buffers(dev, hid);
                goto fail;
@@ -1685,7 +1719,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                        if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-                       usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
+                       usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
                                         hid_irq_in, hid, interval);
                        hid->urbin->transfer_dma = hid->inbuf_dma;
                        hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
index 52437e5e2e7806fa20a81ae67c733ac0dec5d9be..ceebab99eff24e08017efb8e7acf80826aab7d74 100644 (file)
@@ -85,6 +85,23 @@ static const struct hid_usage_entry hid_usage_table[] = {
       {0, 0x91, "D-PadDown"},
       {0, 0x92, "D-PadRight"},
       {0, 0x93, "D-PadLeft"},
+  {  2, 0, "Simulation" },
+      {0, 0xb0, "Aileron"},
+      {0, 0xb1, "AileronTrim"},
+      {0, 0xb2, "Anti-Torque"},
+      {0, 0xb3, "Autopilot"},
+      {0, 0xb4, "Chaff"},
+      {0, 0xb5, "Collective"},
+      {0, 0xb6, "DiveBrake"},
+      {0, 0xb7, "ElectronicCountermeasures"},
+      {0, 0xb8, "Elevator"},
+      {0, 0xb9, "ElevatorTrim"},
+      {0, 0xba, "Rudder"},
+      {0, 0xbb, "Throttle"},
+      {0, 0xbc, "FlightCommunications"},
+      {0, 0xbd, "FlareRelease"},
+      {0, 0xbe, "LandingGear"},
+      {0, 0xbf, "ToeBrake"},
   {  7, 0, "Keyboard" },
   {  8, 0, "LED" },
       {0, 0x01, "NumLock"},
@@ -92,6 +109,7 @@ static const struct hid_usage_entry hid_usage_table[] = {
       {0, 0x03, "ScrollLock"},
       {0, 0x04, "Compose"},
       {0, 0x05, "Kana"},
+      {0, 0x4b, "GenericIndicator"},
   {  9, 0, "Button" },
   { 10, 0, "Ordinal" },
   { 12, 0, "Consumer" },
@@ -574,7 +592,8 @@ static char *keys[KEY_MAX + 1] = {
        [KEY_EXIT] = "Exit",                    [KEY_MOVE] = "Move",
        [KEY_EDIT] = "Edit",                    [KEY_SCROLLUP] = "ScrollUp",
        [KEY_SCROLLDOWN] = "ScrollDown",        [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
-       [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_F13] = "F13",
+       [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
+       [KEY_REDO] = "Redo",                    [KEY_F13] = "F13",
        [KEY_F14] = "F14",                      [KEY_F15] = "F15",
        [KEY_F16] = "F16",                      [KEY_F17] = "F17",
        [KEY_F18] = "F18",                      [KEY_F19] = "F19",
@@ -584,15 +603,15 @@ static char *keys[KEY_MAX + 1] = {
        [KEY_PAUSECD] = "PauseCD",              [KEY_PROG3] = "Prog3",
        [KEY_PROG4] = "Prog4",                  [KEY_SUSPEND] = "Suspend",
        [KEY_CLOSE] = "Close",                  [KEY_PLAY] = "Play",
-       [KEY_FASTFORWARD] = "Fast Forward",     [KEY_BASSBOOST] = "Bass Boost",
+       [KEY_FASTFORWARD] = "FastForward",      [KEY_BASSBOOST] = "BassBoost",
        [KEY_PRINT] = "Print",                  [KEY_HP] = "HP",
        [KEY_CAMERA] = "Camera",                [KEY_SOUND] = "Sound",
        [KEY_QUESTION] = "Question",            [KEY_EMAIL] = "Email",
        [KEY_CHAT] = "Chat",                    [KEY_SEARCH] = "Search",
        [KEY_CONNECT] = "Connect",              [KEY_FINANCE] = "Finance",
        [KEY_SPORT] = "Sport",                  [KEY_SHOP] = "Shop",
-       [KEY_ALTERASE] = "Alternate Erase",     [KEY_CANCEL] = "Cancel",
-       [KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up",
+       [KEY_ALTERASE] = "AlternateErase",      [KEY_CANCEL] = "Cancel",
+       [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
        [KEY_MEDIA] = "Media",                  [KEY_UNKNOWN] = "Unknown",
        [BTN_0] = "Btn0",                       [BTN_1] = "Btn1",
        [BTN_2] = "Btn2",                       [BTN_3] = "Btn3",
@@ -622,8 +641,8 @@ static char *keys[KEY_MAX + 1] = {
        [BTN_TOOL_AIRBRUSH] = "ToolAirbrush",   [BTN_TOOL_FINGER] = "ToolFinger",
        [BTN_TOOL_MOUSE] = "ToolMouse",         [BTN_TOOL_LENS] = "ToolLens",
        [BTN_TOUCH] = "Touch",                  [BTN_STYLUS] = "Stylus",
-       [BTN_STYLUS2] = "Stylus2",              [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
-       [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
+       [BTN_STYLUS2] = "Stylus2",              [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
+       [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
        [BTN_GEAR_UP] = "Gear up",              [KEY_OK] = "Ok",
        [KEY_SELECT] = "Select",                [KEY_GOTO] = "Goto",
        [KEY_CLEAR] = "Clear",                  [KEY_POWER2] = "Power2",
@@ -659,6 +678,9 @@ static char *keys[KEY_MAX + 1] = {
        [KEY_TWEN] = "TWEN",                    [KEY_DEL_EOL] = "DeleteEOL",
        [KEY_DEL_EOS] = "DeleteEOS",            [KEY_INS_LINE] = "InsertLine",
        [KEY_DEL_LINE] = "DeleteLine",
+       [KEY_SEND] = "Send",                    [KEY_REPLY] = "Reply",
+       [KEY_FORWARDMAIL] = "ForwardMail",      [KEY_SAVE] = "Save",
+       [KEY_DOCUMENTS] = "Documents",
 };
 
 static char *relatives[REL_MAX + 1] = {
index 63a4db721f7e5d2e3507b29e76d81c60491ab7c7..0b6452248a398ae38c47848d66416ea6dd07fcfc 100644 (file)
@@ -78,8 +78,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 {
        struct input_dev *input = &hidinput->input;
        struct hid_device *device = hidinput->input.private;
-       int max, code;
-       unsigned long *bit;
+       int max = 0, code;
+       unsigned long *bit = NULL;
 
        field->hidinput = hidinput;
 
@@ -131,6 +131,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        map_key(code);
                        break;
 
+
+               case HID_UP_SIMULATION:
+
+                       switch (usage->hid & 0xffff) {
+                               case 0xba: map_abs(ABS_RUDDER); break;
+                               case 0xbb: map_abs(ABS_THROTTLE); break;
+                       }
+                       break;
+
                case HID_UP_GENDESK:
 
                        if ((usage->hid & 0xf0) == 0x80) {      /* SystemControl */
@@ -238,8 +247,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case 0x000: goto ignore;
                                case 0x034: map_key_clear(KEY_SLEEP);           break;
                                case 0x036: map_key_clear(BTN_MISC);            break;
+                               case 0x045: map_key_clear(KEY_RADIO);           break;
                                case 0x08a: map_key_clear(KEY_WWW);             break;
+                               case 0x08d: map_key_clear(KEY_PROGRAM);         break;
                                case 0x095: map_key_clear(KEY_HELP);            break;
+                               case 0x09c: map_key_clear(KEY_CHANNELUP);       break;
+                               case 0x09d: map_key_clear(KEY_CHANNELDOWN);     break;
                                case 0x0b0: map_key_clear(KEY_PLAY);            break;
                                case 0x0b1: map_key_clear(KEY_PAUSE);           break;
                                case 0x0b2: map_key_clear(KEY_RECORD);          break;
@@ -259,6 +272,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case 0x18a: map_key_clear(KEY_MAIL);            break;
                                case 0x192: map_key_clear(KEY_CALC);            break;
                                case 0x194: map_key_clear(KEY_FILE);            break;
+                               case 0x1a7: map_key_clear(KEY_DOCUMENTS);       break;
+                               case 0x201: map_key_clear(KEY_NEW);             break;
+                               case 0x207: map_key_clear(KEY_SAVE);            break;
+                               case 0x208: map_key_clear(KEY_PRINT);           break;
+                               case 0x209: map_key_clear(KEY_PROPS);           break;
                                case 0x21a: map_key_clear(KEY_UNDO);            break;
                                case 0x21b: map_key_clear(KEY_COPY);            break;
                                case 0x21c: map_key_clear(KEY_CUT);             break;
@@ -271,7 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                                case 0x227: map_key_clear(KEY_REFRESH);         break;
                                case 0x22a: map_key_clear(KEY_BOOKMARKS);       break;
                                case 0x238: map_rel(REL_HWHEEL);                break;
-                               default:    goto unknown;
+                               case 0x279: map_key_clear(KEY_REDO);            break;
+                               case 0x289: map_key_clear(KEY_REPLY);           break;
+                               case 0x28b: map_key_clear(KEY_FORWARDMAIL);     break;
+                               case 0x28c: map_key_clear(KEY_SEND);            break;
+                               default:    goto ignore;
                        }
                        break;
 
@@ -296,9 +318,42 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        break;
 
                case HID_UP_MSVENDOR:
-
                        goto ignore;
 
+               case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
+
+                       set_bit(EV_REP, input->evbit);
+                       switch(usage->hid & HID_USAGE) {
+                               case 0x003: map_key_clear(KEY_FN);              break;
+                               default:    goto ignore;
+                       }
+                       break;
+
+               case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
+
+                       set_bit(EV_REP, input->evbit);
+                       switch(usage->hid & HID_USAGE) {
+                               case 0x004: map_key_clear(KEY_AGAIN);           break;
+                               case 0x00d: map_key_clear(KEY_HOME);            break;
+                               case 0x024: map_key_clear(KEY_SHUFFLE);         break;
+                               case 0x025: map_key_clear(KEY_TV);              break;
+                               case 0x026: map_key_clear(KEY_MENU);            break;
+                               case 0x031: map_key_clear(KEY_AUDIO);           break;
+                               case 0x032: map_key_clear(KEY_SUBTITLE);        break;
+                               case 0x033: map_key_clear(KEY_LAST);            break;
+                               case 0x047: map_key_clear(KEY_MP3);             break;
+                               case 0x048: map_key_clear(KEY_DVD);             break;
+                               case 0x049: map_key_clear(KEY_MEDIA);           break;
+                               case 0x04a: map_key_clear(KEY_VIDEO);           break;
+                               case 0x04b: map_key_clear(KEY_ANGLE);           break;
+                               case 0x04c: map_key_clear(KEY_LANGUAGE);        break;
+                               case 0x04d: map_key_clear(KEY_SUBTITLE);        break;
+                               case 0x051: map_key_clear(KEY_RED);             break;
+                               case 0x052: map_key_clear(KEY_CLOSE);           break;
+                               default:    goto ignore;
+                       }
+                       break;
+
                case HID_UP_PID:
 
                        set_bit(EV_FF, input->evbit);
@@ -349,6 +404,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
        if (usage->code > max)
                goto ignore;
 
+       if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032)))
+               map_rel(REL_HWHEEL);
+
        if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
                 (usage->type == EV_REL) && (usage->code == REL_WHEEL))
                        set_bit(REL_HWHEEL, bit);
index c1b6b69bc4a46979eca2f9b31a6922f9de34f313..ec2412c42f1ea88bebe6a4aade4a2d3e6f82cf4a 100644 (file)
@@ -173,6 +173,7 @@ struct hid_item {
 
 #define HID_UP_UNDEFINED       0x00000000
 #define HID_UP_GENDESK         0x00010000
+#define HID_UP_SIMULATION      0x00020000
 #define HID_UP_KEYBOARD                0x00070000
 #define HID_UP_LED             0x00080000
 #define HID_UP_BUTTON          0x00090000
@@ -182,6 +183,8 @@ struct hid_item {
 #define HID_UP_PID             0x000f0000
 #define HID_UP_HPVENDOR         0xff7f0000
 #define HID_UP_MSVENDOR                0xff000000
+#define HID_UP_CUSTOM          0x00ff0000
+#define HID_UP_LOGIVENDOR      0xffbc0000
 
 #define HID_USAGE              0x0000ffff
 
@@ -242,6 +245,7 @@ struct hid_item {
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_7          0x080
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5          0x100
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON         0x200
+#define HID_QUIRK_2WHEEL_POWERMOUSE            0x400
 
 /*
  * This is the global environment of the parser. This information is
@@ -348,7 +352,8 @@ struct hid_report_enum {
 
 #define HID_REPORT_TYPES 3
 
-#define HID_BUFFER_SIZE                64              /* use 64 for compatibility with all possible packetlen */
+#define HID_MIN_BUFFER_SIZE    64              /* make sure there is at least a packet size of space */
+#define HID_MAX_BUFFER_SIZE    4096            /* 4kb */
 #define HID_CONTROL_FIFO_SIZE  256             /* to init devices with >100 reports */
 #define HID_OUTPUT_FIFO_SIZE   64
 
@@ -386,6 +391,8 @@ struct hid_device {                                                 /* device report descriptor */
 
        unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
 
+       unsigned int bufsize;                                           /* URB buffer size */
+
        struct urb *urbin;                                              /* Input URB */
        char *inbuf;                                                    /* Input buffer */
        dma_addr_t inbuf_dma;                                           /* Input buffer dma */
index 4c13331b5f41d0694f3e44356e92af540de2192d..d32427818af78d590f547e5bcd24efbadef2036a 100644 (file)
@@ -507,6 +507,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        return -EINVAL;
 
                hid_submit_report(hid, report, USB_DIR_OUT);
+               hid_wait_io(hid);
 
                return 0;
 
index 7398a7f19c1e4e994c8de5f2343fc6dcfe6255c3..0fd0fa9fec21f172d703f16fed7e34b246ed35a8 100644 (file)
@@ -260,7 +260,7 @@ static int stv_stop_video (struct usb_stv *dev)
                        PDEBUG (0, "STV(i): Camera set to original resolution");
        }
        /* origMode */
-       kfree (buf);
+       kfree(buf);
        return i;
 }
 
@@ -276,7 +276,7 @@ static int stv_set_video_mode (struct usb_stv *dev)
        }
 
        if ((i = stv_set_config (dev, 1, 0, 0)) < 0) {
-               kfree (buf);
+               kfree(buf);
                return i;
        }
 
@@ -301,13 +301,13 @@ static int stv_set_video_mode (struct usb_stv *dev)
        goto exit;
 
 error:
-       kfree (buf);
+       kfree(buf);
        if (stop_video == 1)
                stv_stop_video (dev);
        return -1;
 
 exit:
-       kfree (buf);
+       kfree(buf);
        return 0;
 }
 
@@ -327,7 +327,7 @@ static int stv_init (struct usb_stv *stv680)
 
        /* set config 1, interface 0, alternate 0 */
        if ((i = stv_set_config (stv680, 1, 0, 0)) < 0) {
-               kfree (buffer);
+               kfree(buffer);
                PDEBUG (0, "STV(e): set config 1,0,0 failed");
                return -1;
        }
@@ -435,11 +435,11 @@ static int stv_init (struct usb_stv *stv680)
 error:
        i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02);     /* Get Last Error */
        PDEBUG (1, "STV(i): last error: %i,  command = 0x%x", buffer[0], buffer[1]);
-       kfree (buffer);
+       kfree(buffer);
        return -1;
 
 exit:
-       kfree (buffer);
+       kfree(buffer);
 
        /* video = 320x240, 352x288 */
        if (stv680->CIF == 1) {
@@ -708,10 +708,10 @@ static int stv680_stop_stream (struct usb_stv *stv680)
                        usb_kill_urb (stv680->urb[i]);
                        usb_free_urb (stv680->urb[i]);
                        stv680->urb[i] = NULL;
-                       kfree (stv680->sbuf[i].data);
+                       kfree(stv680->sbuf[i].data);
                }
        for (i = 0; i < STV680_NUMSCRATCH; i++) {
-               kfree (stv680->scratch[i].data);
+               kfree(stv680->scratch[i].data);
                stv680->scratch[i].data = NULL;
        }
 
@@ -1068,7 +1068,7 @@ static int stv_close (struct inode *inode, struct file *file)
        stv680->user = 0;
 
        if (stv680->removed) {
-               kfree (stv680);
+               kfree(stv680);
                stv680 = NULL;
                PDEBUG (0, "STV(i): device unregistered");
        }
@@ -1445,14 +1445,14 @@ static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
                        usb_kill_urb (stv680->urb[i]);
                        usb_free_urb (stv680->urb[i]);
                        stv680->urb[i] = NULL;
-                       kfree (stv680->sbuf[i].data);
+                       kfree(stv680->sbuf[i].data);
                }
        for (i = 0; i < STV680_NUMSCRATCH; i++)
-               kfree (stv680->scratch[i].data);
+               kfree(stv680->scratch[i].data);
        PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);
 
        /* Free the memory */
-       kfree (stv680);
+       kfree(stv680);
 }
 
 static void stv680_disconnect (struct usb_interface *intf)
index cde0ed097af689d626aac2d699069f7c71b5783b..615874e03ce8bbad26eab9f992b5a43632a02071 100644 (file)
@@ -650,7 +650,6 @@ config FB_NVIDIA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select FB_SOFT_CURSOR
        help
          This driver supports graphics boards with the nVidia chips, TNT
          and newer. For very old chipsets, such as the RIVA128, then use
@@ -681,7 +680,6 @@ config FB_RIVA
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select FB_SOFT_CURSOR
        help
          This driver supports graphics boards with the nVidia Riva/Geforce
          chips.
@@ -720,7 +718,6 @@ config FB_I810
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select FB_SOFT_CURSOR
        help
          This driver supports the on-board graphics built in to the Intel 810 
           and 815 chipsets.  Say Y if you have and plan to use such a board.
@@ -754,6 +751,12 @@ config FB_I810_GTF
   
           If unsure, say N.
 
+config FB_I810_I2C
+       bool "Enable DDC Support"
+       depends on FB_I810 && I2C && FB_I810_GTF
+       select I2C_ALGOBIT
+       help
+
 config FB_INTEL
        tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
        depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
@@ -763,7 +766,6 @@ config FB_INTEL
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select FB_SOFT_CURSOR
        help
          This driver supports the on-board graphics built in to the Intel
           830M/845G/852GM/855GM/865G chipsets.
@@ -960,8 +962,7 @@ config FB_RADEON
          can be build either as modules or built-in.
 
          There is a product page at
-         <http://www.ati.com/na/pages/products/pc/radeon32/index.html>.
-
+         http://apps.ati.com/ATIcompare/
 config FB_RADEON_I2C
        bool "DDC/I2C for ATI Radeon support"
        depends on FB_RADEON
@@ -1084,15 +1085,16 @@ config FB_SAVAGE_ACCEL
           choose N here.
 
 config FB_SIS
-       tristate "SiS acceleration"
+       tristate "SiS/XGI display support"
        depends on FB && PCI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_SOFT_CURSOR
        help
-         This is the frame buffer device driver for the SiS 300, 315 and
-         330 series VGA chipsets. Specs available at <http://www.sis.com>
+         This is the frame buffer device driver for the SiS 300, 315, 330
+         and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
+         Specs available at <http://www.sis.com> and <http://www.xgitech.com>.
 
          To compile this driver as a module, choose M here; the module
          will be called sisfb.
@@ -1104,11 +1106,12 @@ config FB_SIS_300
          Say Y here to support use of the SiS 300/305, 540, 630 and 730.
 
 config FB_SIS_315
-       bool "SiS 315/330 series support"
+       bool "SiS 315/330/340 series and XGI support"
        depends on FB_SIS
        help
-         Say Y here to support use of the SiS 315 and 330 series
-         (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760).
+         Say Y here to support use of the SiS 315, 330 and 340 series
+         (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well
+         as XGI V3XT, V5, V8 and Z7.
 
 config FB_NEOMAGIC
        tristate "NeoMagic display support"
@@ -1180,6 +1183,32 @@ config FB_VOODOO1
          Please read the <file:Documentation/fb/README-sstfb.txt> for supported
          options and other important info  support.
 
+config FB_CYBLA
+       tristate "Cyberblade/i1 support"
+       depends on FB && PCI
+       select FB_CFB_IMAGEBLIT
+       select FB_SOFT_CURSOR
+       select VIDEO_SELECT
+       ---help---
+         This driver is supposed to support the Trident Cyberblade/i1
+         graphics core integrated in the VIA VT8601A North Bridge,
+         also known as VIA Apollo PLE133.
+
+         Status:
+          - Developed, tested and working on EPIA 5000 and EPIA 800.
+          - Does work reliable on all systems with CRT/LCD connected to
+            normal VGA ports.
+          - Should work on systems that do use the internal LCD port, but
+            this is absolutely not tested.
+
+         Character imageblit, copyarea and rectangle fill are hw accelerated,
+         ypan scrolling is used by default.
+
+         Please do read <file:Documentation/fb/cyblafb/*>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cyblafb.
+
 config FB_TRIDENT
        tristate "Trident support"
        depends on FB && PCI
@@ -1193,8 +1222,12 @@ config FB_TRIDENT
          but also on some motherboards. For more information, read
          <file:Documentation/fb/tridentfb.txt>
 
+         Cyberblade/i1 support will be removed soon, use the cyblafb driver
+         instead.
+
          Say Y if you have such a graphics board.
 
+
          To compile this driver as a module, choose M here: the
          module will be called tridentfb.
 
@@ -1205,7 +1238,6 @@ config FB_TRIDENT_ACCEL
        This will compile the Trident frame buffer device with
        acceleration functions.
 
-
 config FB_PM3
        tristate "Permedia3 support"
        depends on FB && PCI && BROKEN
@@ -1484,6 +1516,30 @@ config FB_S1D13XXX
          working with S1D13806). Product specs at
          <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
 
+config FB_S3C2410
+       tristate "S3C2410 LCD framebuffer support"
+       depends on FB && ARCH_S3C2410
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       select FB_SOFT_CURSOR
+       ---help---
+         Frame buffer driver for the built-in LCD controller in the Samsung
+         S3C2410 processor.
+
+         This driver is also available as a module ( = code which can be
+         inserted and removed from the running kernel whenever you want). The
+         module will be called s3c2410fb. If you want to compile it as a module,
+         say M here and read <file:Documentation/modules.txt>.
+
+         If unsure, say N.
+config FB_S3C2410_DEBUG
+       bool "S3C2410 lcd debug messages"
+       depends on FB_S3C2410
+       help
+         Turn on debugging messages. Note that you can set/unset at run time
+         through sysfs
+
 config FB_VIRTUAL
        tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
        depends on FB
index b018df4e95c84377c13ffda88e03dde02f26e467..1fff29f48ca8987cf416d0bd76892d6794f7ccf8 100644 (file)
@@ -9,7 +9,8 @@ obj-$(CONFIG_LOGO)                += logo/
 obj-$(CONFIG_SYSFS)              += backlight/
 
 obj-$(CONFIG_FB)                  += fb.o
-fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o
+fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
+                                     modedb.o fbcvt.o
 fb-objs                           := $(fb-y)
 
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
@@ -50,7 +51,8 @@ obj-$(CONFIG_FB_CT65550)          += chipsfb.o
 obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
 obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o
-obj-$(CONFIG_FB_TRIDENT)         += tridentfb.o
+obj-$(CONFIG_FB_CYBLA)            += cyblafb.o
+obj-$(CONFIG_FB_TRIDENT)          += tridentfb.o
 obj-$(CONFIG_FB_STI)              += stifb.o
 obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
 obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
@@ -92,6 +94,7 @@ obj-$(CONFIG_FB_MAXINE)                 += maxinefb.o
 obj-$(CONFIG_FB_TX3912)                  += tx3912fb.o
 obj-$(CONFIG_FB_S1D13XXX)        += s1d13xxxfb.o
 obj-$(CONFIG_FB_IMX)              += imxfb.o
+obj-$(CONFIG_FB_S3C2410)         += s3c2410fb.o
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
index b0eba3ac6420f61e692118075fa5baf8bce2be4f..e380ee8b0247d629ed65f62557737c2e28d58524 100644 (file)
@@ -806,8 +806,8 @@ static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, stru
 
        /* Very simple test to make sure it appeared */
        if (BIOS_IN16(0) != 0xaa55) {
-               printk(KERN_ERR "aty128fb: Invalid ROM signature %x should be 0xaa55\n",
-                      BIOS_IN16(0));
+               printk(KERN_DEBUG "aty128fb: Invalid ROM signature %x should "
+                       " be 0xaa55\n", BIOS_IN16(0));
                goto failed;
        }
 
index 3e10bd837d9e8382a9f5bf5b0ac7073bb85bdd92..037fe9d32fe39bf19ed41ee1c83671565ab748b9 100644 (file)
@@ -911,20 +911,6 @@ static int aty_var_to_crtc(const struct fb_info *info,
                vdisplay  = par->lcd_height;
 #endif
 
-       if(vdisplay < 400) {
-               h_sync_pol = 1;
-               v_sync_pol = 0;
-       } else if(vdisplay < 480) {
-               h_sync_pol = 0;
-               v_sync_pol = 1;
-       } else if(vdisplay < 768) {
-               h_sync_pol = 0;
-               v_sync_pol = 0;
-       } else {
-               h_sync_pol = 1;
-               v_sync_pol = 1;
-       }
-
        v_disp--;
        v_sync_strt--;
        v_sync_end--;
index e7e8b52014c32cc7695367224f0c4eca2238ba73..046b47860266daa0ec4c45124d124e90c77a941a 100644 (file)
@@ -329,8 +329,9 @@ static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev
 
        /* Very simple test to make sure it appeared */
        if (BIOS_IN16(0) != 0xaa55) {
-               printk(KERN_ERR "radeonfb (%s): Invalid ROM signature %x should be"
-                      "0xaa55\n", pci_name(rinfo->pdev), BIOS_IN16(0));
+               printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x "
+                       "should be 0xaa55\n",
+                       pci_name(rinfo->pdev), BIOS_IN16(0));
                goto failed;
        }
        /* Look for the PCI data to check the ROM type */
@@ -2312,19 +2313,27 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
        rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
 
        /* request the mem regions */
-       ret = pci_request_regions(pdev, "radeonfb");
+       ret = pci_request_region(pdev, 0, "radeonfb framebuffer");
        if (ret < 0) {
-               printk( KERN_ERR "radeonfb (%s): cannot reserve PCI regions."
-                       "  Someone already got them?\n", pci_name(rinfo->pdev));
+               printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n",
+                       pci_name(rinfo->pdev));
                goto err_release_fb;
        }
 
+       ret = pci_request_region(pdev, 2, "radeonfb mmio");
+       if (ret < 0) {
+               printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n",
+                       pci_name(rinfo->pdev));
+               goto err_release_pci0;
+       }
+
        /* map the regions */
        rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
        if (!rinfo->mmio_base) {
-               printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n", pci_name(rinfo->pdev));
+               printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n",
+                      pci_name(rinfo->pdev));
                ret = -EIO;
-               goto err_release_pci;
+               goto err_release_pci2;
        }
 
        rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
@@ -2499,10 +2508,12 @@ err_unmap_rom:
        if (rinfo->bios_seg)
                radeon_unmap_ROM(rinfo, pdev);
        iounmap(rinfo->mmio_base);
-err_release_pci:
-       pci_release_regions(pdev);
+err_release_pci2:
+       pci_release_region(pdev, 2);
+err_release_pci0:
+       pci_release_region(pdev, 0);
 err_release_fb:
-       framebuffer_release(info);
+        framebuffer_release(info);
 err_disable:
        pci_disable_device(pdev);
 err_out:
@@ -2548,7 +2559,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
         iounmap(rinfo->mmio_base);
         iounmap(rinfo->fb_base);
  
-       pci_release_regions(pdev);
+       pci_release_region(pdev, 2);
+       pci_release_region(pdev, 0);
 
        kfree(rinfo->mon1_EDID);
        kfree(rinfo->mon2_EDID);
index 3c731577fed628796423193ca9d99c7be4967671..9f70e512b88bfe0ea54e09c236ec456f5fdc05ac 100644 (file)
@@ -39,7 +39,7 @@ static inline int get_attribute(struct fb_info *info, u16 c)
 {
        int attribute = 0;
 
-       if (fb_get_color_depth(&info->var) == 1) {
+       if (fb_get_color_depth(&info->var, &info->fix) == 1) {
                if (attr_underline(c))
                        attribute |= FBCON_ATTRIBUTE_UNDERLINE;
                if (attr_reverse(c))
@@ -103,42 +103,104 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy,
        info->fbops->fb_fillrect(info, &region);
 }
 
+static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
+                                    const u16 *s, u32 attr, u32 cnt,
+                                    u32 d_pitch, u32 s_pitch, u32 cellsize,
+                                    struct fb_image *image, u8 *buf, u8 *dst)
+{
+       u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+       u32 idx = vc->vc_font.width >> 3;
+       u8 *src;
+
+       while (cnt--) {
+               src = vc->vc_font.data + (scr_readw(s++)&
+                                         charmask)*cellsize;
+
+               if (attr) {
+                       update_attr(buf, src, attr, vc);
+                       src = buf;
+               }
+
+               if (likely(idx == 1))
+                       __fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+                                               image->height);
+               else
+                       fb_pad_aligned_buffer(dst, d_pitch, src, idx,
+                                             image->height);
+
+               dst += s_pitch;
+       }
+
+       info->fbops->fb_imageblit(info, image);
+}
+
+static inline void bit_putcs_unaligned(struct vc_data *vc,
+                                      struct fb_info *info, const u16 *s,
+                                      u32 attr, u32 cnt, u32 d_pitch,
+                                      u32 s_pitch, u32 cellsize,
+                                      struct fb_image *image, u8 *buf,
+                                      u8 *dst)
+{
+       u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+       u32 shift_low = 0, mod = vc->vc_font.width % 8;
+       u32 shift_high = 8;
+       u32 idx = vc->vc_font.width >> 3;
+       u8 *src;
+
+       while (cnt--) {
+               src = vc->vc_font.data + (scr_readw(s++)&
+                                         charmask)*cellsize;
+
+               if (attr) {
+                       update_attr(buf, src, attr, vc);
+                       src = buf;
+               }
+
+               fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
+                                       image->height, shift_high,
+                                       shift_low, mod);
+               shift_low += mod;
+               dst += (shift_low >= 8) ? s_pitch : s_pitch - 1;
+               shift_low &= 7;
+               shift_high = 8 - shift_low;
+       }
+
+       info->fbops->fb_imageblit(info, image);
+
+}
+
 static void bit_putcs(struct vc_data *vc, struct fb_info *info,
                      const unsigned short *s, int count, int yy, int xx,
                      int fg, int bg)
 {
-       unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-       unsigned int width = (vc->vc_font.width + 7) >> 3;
-       unsigned int cellsize = vc->vc_font.height * width;
-       unsigned int maxcnt = info->pixmap.size/cellsize;
-       unsigned int scan_align = info->pixmap.scan_align - 1;
-       unsigned int buf_align = info->pixmap.buf_align - 1;
-       unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
-       unsigned int shift_high = 8, pitch, cnt, size, k;
-       unsigned int idx = vc->vc_font.width >> 3;
-       unsigned int attribute = get_attribute(info, scr_readw(s));
        struct fb_image image;
-       u8 *src, *dst, *buf = NULL;
-
-       if (attribute) {
-               buf = kmalloc(cellsize, GFP_KERNEL);
-               if (!buf)
-                       return;
-       }
+       u32 width = (vc->vc_font.width + 7)/8;
+       u32 cellsize = width * vc->vc_font.height;
+       u32 maxcnt = info->pixmap.size/cellsize;
+       u32 scan_align = info->pixmap.scan_align - 1;
+       u32 buf_align = info->pixmap.buf_align - 1;
+       u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
+       u32 attribute = get_attribute(info, scr_readw(s));
+       u8 *dst, *buf = NULL;
 
        image.fg_color = fg;
        image.bg_color = bg;
-
        image.dx = xx * vc->vc_font.width;
        image.dy = yy * vc->vc_font.height;
        image.height = vc->vc_font.height;
        image.depth = 1;
 
+       if (attribute) {
+               buf = kmalloc(cellsize, GFP_KERNEL);
+               if (!buf)
+                       return;
+       }
+
        while (count) {
                if (count > maxcnt)
-                       cnt = k = maxcnt;
+                       cnt = maxcnt;
                else
-                       cnt = k = count;
+                       cnt = count;
 
                image.width = vc->vc_font.width * cnt;
                pitch = ((image.width + 7) >> 3) + scan_align;
@@ -147,41 +209,18 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
                size &= ~buf_align;
                dst = fb_get_buffer_offset(info, &info->pixmap, size);
                image.data = dst;
-               if (mod) {
-                       while (k--) {
-                               src = vc->vc_font.data + (scr_readw(s++)&
-                                                         charmask)*cellsize;
-
-                               if (attribute) {
-                                       update_attr(buf, src, attribute, vc);
-                                       src = buf;
-                               }
-
-                               fb_pad_unaligned_buffer(dst, pitch, src, idx,
-                                               image.height, shift_high,
-                                               shift_low, mod);
-                               shift_low += mod;
-                               dst += (shift_low >= 8) ? width : width - 1;
-                               shift_low &= 7;
-                               shift_high = 8 - shift_low;
-                       }
-               } else {
-                       while (k--) {
-                               src = vc->vc_font.data + (scr_readw(s++)&
-                                                         charmask)*cellsize;
-
-                               if (attribute) {
-                                       update_attr(buf, src, attribute, vc);
-                                       src = buf;
-                               }
-
-                               fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
-                               dst += width;
-                       }
-               }
-               info->fbops->fb_imageblit(info, &image);
+
+               if (!mod)
+                       bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
+                                         width, cellsize, &image, buf, dst);
+               else
+                       bit_putcs_unaligned(vc, info, s, attribute, cnt,
+                                           pitch, width, cellsize, &image,
+                                           buf, dst);
+
                image.dx += cnt * vc->vc_font.width;
                count -= cnt;
+               s += cnt;
        }
 
        /* buf is always NULL except when in monochrome mode, so in this case
@@ -189,6 +228,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
           NULL pointers just fine */
        if (unlikely(buf))
                kfree(buf);
+
 }
 
 static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
index 35c88bd7ba5e43d16bb49c08bb76ad5ddd43541d..2e93224d2d5509a14ce09ae25bd524e78f014742 100644 (file)
@@ -214,7 +214,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
 static inline int get_color(struct vc_data *vc, struct fb_info *info,
              u16 c, int is_fg)
 {
-       int depth = fb_get_color_depth(&info->var);
+       int depth = fb_get_color_depth(&info->var, &info->fix);
        int color = 0;
 
        if (console_blanked) {
@@ -230,9 +230,13 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
        switch (depth) {
        case 1:
        {
+               int col = ~(0xfff << (max(info->var.green.length,
+                                         max(info->var.red.length,
+                                             info->var.blue.length)))) & 0xff;
+
                /* 0 or 1 */
-               int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
-               int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
+               int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
+               int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
 
                if (console_blanked)
                        fg = bg;
@@ -243,9 +247,25 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
        case 2:
                /*
                 * Scale down 16-colors to 4 colors. Default 4-color palette
-                * is grayscale.
+                * is grayscale. However, simply dividing the values by 4
+                * will not work, as colors 1, 2 and 3 will be scaled-down
+                * to zero rendering them invisible.  So empirically convert
+                * colors to a sane 4-level grayscale.
                 */
-               color /= 4;
+               switch (color) {
+               case 0:
+                       color = 0; /* black */
+                       break;
+               case 1 ... 6:
+                       color = 2; /* white */
+                       break;
+               case 7 ... 8:
+                       color = 1; /* gray */
+                       break;
+               default:
+                       color = 3; /* intense white */
+                       break;
+               }
                break;
        case 3:
                /*
@@ -311,6 +331,35 @@ static void cursor_timer_handler(unsigned long dev_addr)
        mod_timer(&ops->cursor_timer, jiffies + HZ/5);
 }
 
+static void fbcon_add_cursor_timer(struct fb_info *info)
+{
+       struct fbcon_ops *ops = info->fbcon_par;
+
+       if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
+           !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
+               if (!info->queue.func)
+                       INIT_WORK(&info->queue, fb_flashcursor, info);
+
+               init_timer(&ops->cursor_timer);
+               ops->cursor_timer.function = cursor_timer_handler;
+               ops->cursor_timer.expires = jiffies + HZ / 5;
+               ops->cursor_timer.data = (unsigned long ) info;
+               add_timer(&ops->cursor_timer);
+               ops->flags |= FBCON_FLAGS_CURSOR_TIMER;
+       }
+}
+
+static void fbcon_del_cursor_timer(struct fb_info *info)
+{
+       struct fbcon_ops *ops = info->fbcon_par;
+
+       if (info->queue.func == fb_flashcursor &&
+           ops->flags & FBCON_FLAGS_CURSOR_TIMER) {
+               del_timer_sync(&ops->cursor_timer);
+               ops->flags &= ~FBCON_FLAGS_CURSOR_TIMER;
+       }
+}
+
 #ifndef MODULE
 static int __init fb_console_setup(char *this_opt)
 {
@@ -426,7 +475,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
         * remove underline attribute from erase character
         * if black and white framebuffer.
         */
-       if (fb_get_color_depth(&info->var) == 1)
+       if (fb_get_color_depth(&info->var, &info->fix) == 1)
                erase &= ~0x400;
        logo_height = fb_prepare_logo(info);
        logo_lines = (logo_height + vc->vc_font.height - 1) /
@@ -563,9 +612,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
        }
 
        if (!err) {
-               if (oldinfo->queue.func == fb_flashcursor)
-                       del_timer_sync(&ops->cursor_timer);
-
+               fbcon_del_cursor_timer(oldinfo);
                kfree(ops->cursor_state.mask);
                kfree(ops->cursor_data);
                kfree(oldinfo->fbcon_par);
@@ -576,22 +623,6 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
        return err;
 }
 
-static void con2fb_init_newinfo(struct fb_info *info)
-{
-       if (!info->queue.func || info->queue.func == fb_flashcursor) {
-               struct fbcon_ops *ops = info->fbcon_par;
-
-               if (!info->queue.func)
-                       INIT_WORK(&info->queue, fb_flashcursor, info);
-
-               init_timer(&ops->cursor_timer);
-               ops->cursor_timer.function = cursor_timer_handler;
-               ops->cursor_timer.expires = jiffies + HZ / 5;
-               ops->cursor_timer.data = (unsigned long ) info;
-               add_timer(&ops->cursor_timer);
-       }
-}
-
 static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
                                int unit, int show_logo)
 {
@@ -675,7 +706,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
                                 logo_shown != FBCON_LOGO_DONTSHOW);
 
                if (!found)
-                       con2fb_init_newinfo(info);
+                       fbcon_add_cursor_timer(info);
                con2fb_map_boot[unit] = newidx;
                con2fb_init_display(vc, info, unit, show_logo);
        }
@@ -878,18 +909,7 @@ static const char *fbcon_startup(void)
        }
 #endif                         /* CONFIG_MAC */
 
-       /* Initialize the work queue. If the driver provides its
-        * own work queue this means it will use something besides 
-        * default timer to flash the cursor. */
-       if (!info->queue.func) {
-               INIT_WORK(&info->queue, fb_flashcursor, info);
-
-               init_timer(&ops->cursor_timer);
-               ops->cursor_timer.function = cursor_timer_handler;
-               ops->cursor_timer.expires = jiffies + HZ / 5;
-               ops->cursor_timer.data = (unsigned long ) info;
-               add_timer(&ops->cursor_timer);
-       }
+       fbcon_add_cursor_timer(info);
        return display_desc;
 }
 
@@ -930,7 +950,7 @@ static void fbcon_init(struct vc_data *vc, int init)
        }
        if (p->userfont)
                charcnt = FNTCHARCNT(p->fontdata);
-       vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
+       vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
        vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
        if (charcnt == 256) {
                vc->vc_hi_font_mask = 0;
@@ -1178,7 +1198,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
        if (p->userfont)
                charcnt = FNTCHARCNT(p->fontdata);
 
-       vc->vc_can_do_color = (fb_get_color_depth(var) != 1);
+       var->activate = FB_ACTIVATE_NOW;
+       info->var.activate = var->activate;
+       info->var.yoffset = info->var.xoffset = 0;
+       fb_set_var(info, var);
+
+       vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
        vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
        if (charcnt == 256) {
                vc->vc_hi_font_mask = 0;
@@ -1898,7 +1923,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
 
 static int fbcon_switch(struct vc_data *vc)
 {
-       struct fb_info *info;
+       struct fb_info *info, *old_info = NULL;
        struct display *p = &fb_display[vc->vc_num];
        struct fb_var_screeninfo var;
        int i, prev_console;
@@ -1931,7 +1956,8 @@ static int fbcon_switch(struct vc_data *vc)
        }
 
        prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon;
-
+       if (prev_console != -1)
+               old_info = registered_fb[con2fb_map[prev_console]];
        /*
         * FIXME: If we have multiple fbdev's loaded, we need to
         * update all info->currcon.  Perhaps, we can place this
@@ -1959,15 +1985,17 @@ static int fbcon_switch(struct vc_data *vc)
        info->var.yoffset = info->var.xoffset = p->yscroll = 0;
        fb_set_var(info, &var);
 
-       if (prev_console != -1 &&
-           registered_fb[con2fb_map[prev_console]] != info &&
-           info->fbops->fb_set_par)
-               info->fbops->fb_set_par(info);
+       if (old_info != NULL && old_info != info) {
+               if (info->fbops->fb_set_par)
+                       info->fbops->fb_set_par(info);
+               fbcon_del_cursor_timer(old_info);
+               fbcon_add_cursor_timer(info);
+       }
 
        set_blitting_type(vc, info, p);
        ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
 
-       vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
+       vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
        vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
        updatescrollmode(p, info, vc);
 
@@ -2048,11 +2076,16 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
                                fbcon_generic_blank(vc, info, blank);
                }
 
-               if (!blank)
-                       update_screen(vc);
-       }
+               if (!blank)
+                       update_screen(vc);
+       }
 
-       return 0;
+       if (!blank)
+               fbcon_add_cursor_timer(info);
+       else
+               fbcon_del_cursor_timer(info);
+
+       return 0;
 }
 
 static void fbcon_free_font(struct display *p)
@@ -2332,7 +2365,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
        if (!CON_IS_VISIBLE(vc))
                return 0;
 
-       depth = fb_get_color_depth(&info->var);
+       depth = fb_get_color_depth(&info->var, &info->fix);
        if (depth > 3) {
                for (i = j = 0; i < 16; i++) {
                        k = table[i];
@@ -2593,6 +2626,51 @@ static void fbcon_modechanged(struct fb_info *info)
        }
 }
 
+static void fbcon_set_all_vcs(struct fb_info *info)
+{
+       struct fbcon_ops *ops = info->fbcon_par;
+       struct vc_data *vc;
+       struct display *p;
+       int i, rows, cols;
+
+       if (!ops || ops->currcon < 0)
+               return;
+
+       for (i = 0; i < MAX_NR_CONSOLES; i++) {
+               vc = vc_cons[i].d;
+               if (!vc || vc->vc_mode != KD_TEXT ||
+                   registered_fb[con2fb_map[i]] != info)
+                       continue;
+
+               p = &fb_display[vc->vc_num];
+
+               info->var.xoffset = info->var.yoffset = p->yscroll = 0;
+               var_to_display(p, &info->var, info);
+               cols = info->var.xres / vc->vc_font.width;
+               rows = info->var.yres / vc->vc_font.height;
+               vc_resize(vc, cols, rows);
+
+               if (CON_IS_VISIBLE(vc)) {
+                       updatescrollmode(p, info, vc);
+                       scrollback_max = 0;
+                       scrollback_current = 0;
+                       update_var(vc->vc_num, info);
+                       fbcon_set_palette(vc, color_table);
+                       update_screen(vc);
+                       if (softback_buf) {
+                               int l = fbcon_softback_size / vc->vc_size_row;
+                               if (l > 5)
+                                       softback_end = softback_buf + l * vc->vc_size_row;
+                               else {
+                                       /* Smaller scrollback makes no sense, and 0
+                                          would screw the operation totally */
+                                       softback_top = 0;
+                               }
+                       }
+               }
+       }
+}
+
 static int fbcon_mode_deleted(struct fb_info *info,
                              struct fb_videomode *mode)
 {
@@ -2708,6 +2786,9 @@ static int fbcon_event_notify(struct notifier_block *self,
        case FB_EVENT_MODE_CHANGE:
                fbcon_modechanged(info);
                break;
+       case FB_EVENT_MODE_CHANGE_ALL:
+               fbcon_set_all_vcs(info);
+               break;
        case FB_EVENT_MODE_DELETE:
                mode = event->data;
                ret = fbcon_mode_deleted(info, mode);
index 5d377860bce28319738c22a820860c52f182e4dc..08befafe11d14c82f822f078e4fb50467dad2361 100644 (file)
@@ -18,7 +18,8 @@
 
 #include <asm/io.h>
 
-#define FBCON_FLAGS_INIT 1
+#define FBCON_FLAGS_INIT         1
+#define FBCON_FLAGS_CURSOR_TIMER 2
 
    /*
     *    This is the interface between the low-level console driver and the
index d27fa91e58869edf4e834b7d7a5b43ae01f8292c..0705cd7414117a26cb9d451d478c665a4c83fbfd 100644 (file)
@@ -497,6 +497,57 @@ static void vgacon_cursor(struct vc_data *c, int mode)
        }
 }
 
+static int vgacon_doresize(struct vc_data *c,
+               unsigned int width, unsigned int height)
+{
+       unsigned long flags;
+       unsigned int scanlines = height * c->vc_font.height;
+       u8 scanlines_lo, r7, vsync_end, mode;
+
+       spin_lock_irqsave(&vga_lock, flags);
+
+       outb_p(VGA_CRTC_MODE, vga_video_port_reg);
+       mode = inb_p(vga_video_port_val);
+
+       if (mode & 0x04)
+               scanlines >>= 1;
+
+       scanlines -= 1;
+       scanlines_lo = scanlines & 0xff;
+
+       outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+       r7 = inb_p(vga_video_port_val) & ~0x42;
+
+       if (scanlines & 0x100)
+               r7 |= 0x02;
+       if (scanlines & 0x200)
+               r7 |= 0x40;
+
+       /* deprotect registers */
+       outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+       vsync_end = inb_p(vga_video_port_val);
+       outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+       outb_p(vsync_end & ~0x80, vga_video_port_val);
+
+       outb_p(VGA_CRTC_H_DISP, vga_video_port_reg);
+       outb_p(width - 1, vga_video_port_val);
+       outb_p(VGA_CRTC_OFFSET, vga_video_port_reg);
+       outb_p(width >> 1, vga_video_port_val);
+
+       outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg);
+       outb_p(scanlines_lo, vga_video_port_val);
+       outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg);
+       outb_p(r7,vga_video_port_val);
+
+       /* reprotect registers */
+       outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg);
+       outb_p(vsync_end, vga_video_port_val);
+
+       spin_unlock_irqrestore(&vga_lock, flags);
+
+       return 0;
+}
+
 static int vgacon_switch(struct vc_data *c)
 {
        /*
@@ -510,9 +561,13 @@ static int vgacon_switch(struct vc_data *c)
        /* We can only copy out the size of the video buffer here,
         * otherwise we get into VGA BIOS */
 
-       if (!vga_is_gfx)
+       if (!vga_is_gfx) {
                scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
-                           c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
+                           c->vc_screenbuf_size > vga_vram_size ?
+                               vga_vram_size : c->vc_screenbuf_size);
+               vgacon_doresize(c, c->vc_cols, c->vc_rows);
+       }
+
        return 0;               /* Redrawing not needed */
 }
 
@@ -962,6 +1017,17 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
 
 #endif
 
+static int vgacon_resize(struct vc_data *c, unsigned int width,
+                               unsigned int height)
+{
+       if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES)
+               return -EINVAL;
+
+       if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
+               vgacon_doresize(c, width, height);
+       return 0;
+}
+
 static int vgacon_scrolldelta(struct vc_data *c, int lines)
 {
        if (!lines)             /* Turn scrollback off */
@@ -1103,6 +1169,7 @@ const struct consw vga_con = {
        .con_blank = vgacon_blank,
        .con_font_set = vgacon_font_set,
        .con_font_get = vgacon_font_get,
+       .con_resize = vgacon_resize,
        .con_set_palette = vgacon_set_palette,
        .con_scrolldelta = vgacon_scrolldelta,
        .con_set_origin = vgacon_set_origin,
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
new file mode 100644 (file)
index 0000000..ae2762c
--- /dev/null
@@ -0,0 +1,1456 @@
+/*
+ * Frame buffer driver for Trident Cyberblade/i1 graphics core
+ *
+ * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de>
+ *
+ * CREDITS:
+ *     tridentfb.c by Jani Monoses
+ *     see files above for further credits
+ *
+ * TODO:
+ *
+ */
+
+#define CYBLAFB_DEBUG 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/types.h>
+#include <video/cyblafb.h>
+
+#define VERSION "0.54"
+
+struct cyblafb_par {
+       u32 pseudo_pal[16];
+       struct fb_ops ops;
+};
+
+static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
+       .id = "CyBla",
+       .type = FB_TYPE_PACKED_PIXELS,
+       .ypanstep = 1,
+       .visual = FB_VISUAL_PSEUDOCOLOR,
+       .accel = FB_ACCEL_NONE,
+};
+
+static char *mode __devinitdata = NULL;
+static int bpp __devinitdata = 8;
+static int ref __devinitdata = 75;
+static int fp __devinitdata;
+static int crt __devinitdata;
+static int memsize __devinitdata;
+static int vesafb __devinitdata;
+
+static int nativex;
+static int center;
+static int stretch;
+static int pciwb = 1;
+static int pcirb = 1;
+static int pciwr = 1;
+static int pcirr = 1;
+static int verbosity;
+static int displaytype;
+
+static void __iomem * io_virt; // iospace virtual memory address
+
+module_param(mode,charp,0);
+module_param(bpp,int,0);
+module_param(ref,int,0);
+module_param(fp,int,0);
+module_param(crt,int,0);
+module_param(nativex,int,0);
+module_param(center,int,0);
+module_param(stretch,int,0);
+module_param(pciwb,int,0);
+module_param(pcirb,int,0);
+module_param(pciwr,int,0);
+module_param(pcirr,int,0);
+module_param(memsize,int,0);
+module_param(verbosity,int,0);
+module_param(vesafb,int,0);
+
+//=========================================
+//
+// Port access macros for memory mapped io
+//
+//=========================================
+
+#define out8(r,v) writeb(v,io_virt+r)
+#define out32(r,v) writel(v,io_virt+r)
+#define in8(r) readb(io_virt+r)
+#define in32(r) readl(io_virt+r)
+
+//======================================
+//
+// Hardware access inline functions
+//
+//======================================
+
+static inline unsigned char read3X4(int reg)
+{
+       out8(0x3D4,reg);
+       return in8(0x3D5);
+}
+
+static inline unsigned char read3C4(int reg)
+{
+       out8(0x3C4,reg);
+       return in8(0x3C5);
+}
+
+static inline unsigned char read3CE(int reg)
+{
+       out8(0x3CE,reg);
+       return in8(0x3CF);
+}
+
+static inline void write3X4(int reg,unsigned char val)
+{
+       out8(0x3D4,reg);
+       out8(0x3D5,val);
+}
+
+static inline void write3C4(int reg,unsigned char val)
+{
+       out8(0x3C4,reg);
+       out8(0x3C5,val);
+}
+
+static inline void write3CE(int reg,unsigned char val)
+{
+       out8(0x3CE,reg);
+       out8(0x3CF,val);
+}
+
+static inline void write3C0(int reg,unsigned char val)
+{
+       in8(0x3DA);     // read to reset index
+       out8(0x3C0,reg);
+       out8(0x3C0,val);
+}
+
+//=================================================
+//
+// Enable memory mapped io and unprotect registers
+//
+//=================================================
+
+static inline void enable_mmio(void)
+{
+       int tmp;
+
+       outb(0x0B,0x3C4);
+       inb(0x3C5);             // Set NEW mode
+       outb(SR0E,0x3C4);       // write enable a lot of extended ports
+       outb(0x80,0x3C5);
+
+       outb(SR11,0x3C4);       // write enable those extended ports that
+       outb(0x87,0x3C5);       // are not affected by SR0E_New
+
+       outb(CR1E,0x3d4);       // clear write protect bit for port 0x3c2
+       tmp=inb(0x3d5) & 0xBF;
+       outb(CR1E,0x3d4);
+       outb(tmp,0x3d5);
+
+       outb(CR39,0x3D4);
+       outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched
+}
+
+//=================================================
+//
+// Set pixel clock VCLK1
+//   - multipliers set elswhere
+//   - freq in units of 0.01 MHz
+//
+//=================================================
+
+static void set_vclk(struct cyblafb_par *par, int freq)
+{
+       u32 m,n,k;
+       int f,fi,d,di;
+       u8 lo=0,hi=0;
+
+       d = 2000;
+       k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
+       for(m = 0;m<64;m++)
+       for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 !
+               fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12);
+               if ((di = abs(fi - freq)) < d) {
+                       d = di;
+                       f = fi;
+                       lo = (u8) n;
+                       hi = (u8) ((k<<6) | m);
+               }
+       }
+       write3C4(SR19,hi);
+       write3C4(SR18,lo);
+       if(verbosity > 1)
+               output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
+               freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+}
+
+//================================================
+//
+// Cyberblade specific Graphics Engine (GE) setup
+//
+//================================================
+
+static void cyblafb_setup_GE(int pitch,int bpp)
+{
+       int base = (pitch>>3)<<20;
+
+       switch (bpp) {
+               case  8: base |= (0<<29); break;
+               case 15: base |= (5<<29); break;
+               case 16: base |= (1<<29); break;
+               case 24:
+               case 32: base |= (2<<29); break;
+       }
+
+       write3X4(CR36,0x90);    // reset GE
+       write3X4(CR36,0x80);    // enable GE
+
+       out32(GE24,1<<7);       // reset all GE pointers
+       out32(GE24,0);
+
+       write3X4(CR2D,0x00);    // GE Timinigs, no delays
+
+       out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133
+       out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133
+       out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133
+       out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133
+       out32(GEC8,base); // Source Stride / Buffer Base 0, p 133
+       out32(GECC,base); // Source Stride / Buffer Base 1, p 133
+       out32(GED0,base); // Source Stride / Buffer Base 2, p 133
+       out32(GED4,base); // Source Stride / Buffer Base 3, p 133
+       out32(GE6C,0);    // Pattern and Style, p 129, ok
+}
+
+//=====================================================================
+//
+// Although this is a .fb_sync function that could be enabled in
+// cyblafb_ops, we do not include it there. We sync immediately before
+// new GE operations to improve performance.
+//
+//=====================================================================
+
+static int cyblafb_sync(struct fb_info *info)
+{
+       int status, i=100000;
+       while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+               i--;
+
+       if (i == 0) {
+               // The timeout might be caused by disabled mmio.
+               // Cause:
+               //   - bit CR39 & 1 == 0 upon return, X trident driver bug
+               //   - kdm bug (KD_GRAPHICS not set on first switch)
+               //   - kernel design flaw (it believes in the correctness
+               //     of kdm/X
+               // So we make sure that mmio is enabled first ...
+               enable_mmio();
+//             show_trace(NULL,&status);
+               i=1000000;
+               while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+                       i--;
+               if (i == 0) {
+                       output("GE Timeout, status: %x\n",status);
+                       if(status & 0x80000000)
+                               output("Bresenham Engine : Busy\n");
+                       if(status & 0x40000000)
+                               output("Setup Engine     : Busy\n");
+                       if(status & 0x20000000)
+                               output("SP / DPE         : Busy\n");
+                       if(status & 0x10000000)
+                               output("Memory Interface : Busy\n");
+                       if(status & 0x08000000)
+                               output("Com Lst Proc     : Busy\n");
+                       if(status & 0x04000000)
+                               output("Block Write      : Busy\n");
+                       if(status & 0x02000000)
+                               output("Command Buffer   : Full\n");
+                       if(status & 0x01000000)
+                               output("RESERVED         : Busy\n");
+                       if(status & 0x00800000)
+                               output("PCI Write Buffer : Busy\n");
+                       cyblafb_setup_GE(info->var.xres,
+                                        info->var.bits_per_pixel);
+               }
+       }
+
+       return 0;
+}
+
+//==============================
+//
+// Cyberblade specific fillrect
+//
+//==============================
+
+static void cyblafb_fillrect(struct fb_info * info,
+                            const struct fb_fillrect *fr)
+{
+       int bpp = info->var.bits_per_pixel;
+       int col;
+
+       switch (bpp) {
+               default:
+               case 8: col = fr->color;
+                       col |= col <<8;
+                       col |= col <<16;
+                       break;
+               case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
+                        col |= col <<16;
+                        break;
+               case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
+                        break;
+       }
+
+       cyblafb_sync(info);
+
+       out32(GE60,col);
+       out32(GE48,fr->rop ? 0x66:ROP_S);
+       out32(GE44,0x20000000|1<<19|1<<4|2<<2);
+       out32(GE08,point(fr->dx,fr->dy));
+       out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1));
+
+}
+
+//==============================
+//
+// Cyberblade specific copyarea
+//
+//==============================
+
+static void cyblafb_copyarea(struct fb_info *info,
+                            const struct fb_copyarea *ca)
+{
+       __u32 s1,s2,d1,d2;
+       int direction;
+
+       s1 = point(ca->sx,ca->sy);
+       s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1);
+       d1 = point(ca->dx,ca->dy);
+       d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1);
+       if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
+               direction = 0;
+       else
+               direction = 2;
+
+       cyblafb_sync(info);
+
+       out32(GE44,0xa0000000|1<<19|1<<2|direction);
+       out32(GE00,direction?s2:s1);
+       out32(GE04,direction?s1:s2);
+       out32(GE08,direction?d2:d1);
+       out32(GE0C,direction?d1:d2);
+
+}
+
+//=======================================================================
+//
+// Cyberblade specific imageblit
+//
+// Accelerated for the most usual case, blitting 1-bit deep character
+// character images. Everything else is passed to the generic imageblit.
+//
+//=======================================================================
+
+static void cyblafb_imageblit(struct fb_info *info,
+                             const struct fb_image *image)
+{
+
+       u32 fgcol, bgcol;
+
+       int i;
+       int bpp = info->var.bits_per_pixel;
+       int index = 0;
+       int index_end=image->height * image->width / 8;
+       int width_dds=image->width / 32;
+       int width_dbs=image->width % 32;
+
+       if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 ||
+           image->width % 8 != 0 || image->width == 0 || image->height == 0) {
+               cfb_imageblit(info,image);
+               return;
+       }
+
+       if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+           info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+               fgcol = ((u32*)(info->pseudo_palette))[image->fg_color];
+               bgcol = ((u32*)(info->pseudo_palette))[image->bg_color];
+       } else {
+               fgcol = image->fg_color;
+               bgcol = image->bg_color;
+       }
+
+       switch (bpp) {
+               case 8:
+                       fgcol |= fgcol <<8; fgcol |= fgcol <<16;
+                       bgcol |= bgcol <<8; bgcol |= bgcol <<16;
+                       break;
+               case 16:
+                       fgcol |= fgcol <<16;
+                       bgcol |= bgcol <<16;
+                       break;
+               default:
+                        break;
+       }
+
+       cyblafb_sync(info);
+
+       out32(GE60,fgcol);
+       out32(GE64,bgcol);
+       out32(GE44,0xa0000000 | 1<<20 | 1<<19);
+       out32(GE08,point(image->dx,image->dy));
+       out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1));
+
+       while(index < index_end) {
+               for(i=0;i<width_dds;i++) {
+                       out32(GE9C,*((u32*) ((u32)image->data + index)));
+                       index+=4;
+               }
+               switch(width_dbs) {
+               case 0: break;
+               case 8: out32(GE9C,*((u8*)((u32)image->data+index)));
+                       index+=1;
+                       break;
+               case 16: out32(GE9C,*((u16*)((u32)image->data+index)));
+                       index+=2;
+                       break;
+               case 24: out32(GE9C,(u32)(*((u16*)((u32)image->data+index))) |
+                              (u32)(*((u8*)((u32)image->data+index+2)))<<16);
+                       index+=3;
+                       break;
+               }
+       }
+}
+
+//==========================================================
+//
+// Check if video mode is acceptable. We change var->??? if
+// video mode is slightly off or return error otherwise.
+// info->??? must not be changed!
+//
+//==========================================================
+
+static int cyblafb_check_var(struct fb_var_screeninfo *var,
+                            struct fb_info *info)
+{
+       int bpp = var->bits_per_pixel;
+       int s,t,maxvyres;
+
+       //
+       // we try to support 8, 16, 24 and 32 bpp modes,
+       // default to 8
+       //
+       // there is a 24 bpp mode, but for now we change requests to 32 bpp
+       // (This is what tridentfb does ... will be changed in the future)
+       //
+       //
+       if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+               bpp = 8;
+       if (bpp == 24 )
+               bpp = var->bits_per_pixel = 32;
+
+       //
+       // interlaced modes are broken, fail if one is requested
+       //
+       if (var->vmode & FB_VMODE_INTERLACED)
+               return -EINVAL;
+
+       //
+       // fail if requested resolution is higher than physical
+       // flatpanel resolution
+       //
+       if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex)
+               return -EINVAL;
+
+       //
+       // xres != xres_virtual is broken, fail if such an
+       // unusual mode is requested
+       //
+       if (var->xres != var->xres_virtual)
+               return -EINVAL;
+
+       //
+       // we do not allow vclk to exceed 230 MHz
+       //
+       if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
+               return -EINVAL;
+
+       //
+       // calc max yres_virtual that would fit in memory
+       // and max yres_virtual that could be used for scrolling
+       // and use minimum of the results as maxvyres
+       //
+       // adjust vyres_virtual to maxvyres if necessary
+       // fail if requested yres is bigger than maxvyres
+       //
+       s = (0x1fffff / (var->xres * bpp/8)) + var->yres;
+       t = info->fix.smem_len / (var->xres * bpp/8);
+       maxvyres = t < s ? t : s;
+       if (maxvyres < var->yres_virtual)
+               var->yres_virtual=maxvyres;
+       if (maxvyres < var->yres)
+               return -EINVAL;
+
+       switch (bpp) {
+               case 8:
+                       var->red.offset = 0;
+                       var->green.offset = 0;
+                       var->blue.offset = 0;
+                       var->red.length = 6;
+                       var->green.length = 6;
+                       var->blue.length = 6;
+                       break;
+               case 16:
+                       var->red.offset = 11;
+                       var->green.offset = 5;
+                       var->blue.offset = 0;
+                       var->red.length = 5;
+                       var->green.length = 6;
+                       var->blue.length = 5;
+                       break;
+               case 32:
+                       var->red.offset = 16;
+                       var->green.offset = 8;
+                       var->blue.offset = 0;
+                       var->red.length = 8;
+                       var->green.length = 8;
+                       var->blue.length = 8;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       return 0;
+
+}
+
+//=====================================================================
+//
+// Pan the display
+//
+// The datasheets defines crt start address to be 20 bits wide and
+// to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is
+// CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use
+// it, so it is also safe to be used here. BTW: datasheet CR0E on page
+// 90 really is CR1E, the real CRE is documented on page 72.
+//
+//=====================================================================
+
+static int cyblafb_pan_display(struct fb_var_screeninfo *var,
+                              struct fb_info *info)
+{
+       unsigned int offset;
+
+       offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32;
+       info->var.xoffset = var->xoffset;
+       info->var.yoffset = var->yoffset;
+
+       write3X4(CR0D,offset & 0xFF);
+       write3X4(CR0C,(offset & 0xFF00) >> 8);
+       write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11));
+       write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17));
+       write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15));
+
+       return 0;
+}
+
+//============================================
+//
+// This will really help in case of a bug ...
+// dump most gaphics core registers.
+//
+//============================================
+
+static void regdump(struct cyblafb_par *par)
+{
+       int i;
+
+       if (verbosity < 2)
+               return;
+
+       printk("\n");
+       for(i=0; i<=0xff; i++) {
+               outb(i,0x3d4);
+               printk("CR%02x=%02x ",i,inb(0x3d5));
+               if (i%16==15)
+                       printk("\n");
+       }
+
+       outb(0x30,0x3ce);
+       outb(inb(0x3cf) | 0x40,0x3cf);
+       for(i=0; i<=0x1f; i++) {
+               if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) {
+                       outb(i,0x3d4);
+                       printk("CR%02x=%02x ",i,inb(0x3d5));
+               } else
+                       printk("------- ");
+               if (i%16==15)
+                       printk("\n");
+       }
+       outb(0x30,0x3ce);
+       outb(inb(0x3cf) & 0xbf,0x3cf);
+
+       printk("\n");
+       for(i=0; i<=0x7f; i++) {
+               outb(i,0x3ce);
+               printk("GR%02x=%02x ",i,inb(0x3cf));
+               if (i%16==15)
+                       printk("\n");
+       }
+
+       printk("\n");
+       for(i=0; i<=0xff; i++) {
+               outb(i,0x3c4);
+               printk("SR%02x=%02x ",i,inb(0x3c5));
+               if (i%16==15)
+                       printk("\n");
+       }
+
+       printk("\n");
+       for(i=0; i <= 0x1F; i++) {
+               inb(0x3da); // next access is index!
+               outb(i,0x3c0);
+               printk("AR%02x=%02x ",i,inb(0x3c1));
+               if (i%16==15)
+                       printk("\n");
+       }
+       printk("\n");
+
+       inb(0x3DA);                     // reset internal flag to 3c0 index
+       outb(0x20,0x3C0);               // enable attr
+
+       return;
+}
+
+//======================================
+//
+// Set hardware to requested video mode
+//
+//======================================
+
+static int cyblafb_set_par(struct fb_info *info)
+{
+       struct cyblafb_par *par = info->par;
+       u32
+       htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch,
+               vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend;
+       struct fb_var_screeninfo *var = &info->var;
+       int bpp = var->bits_per_pixel;
+       int i;
+
+       if (verbosity > 0)
+               output("Switching to new mode: "
+                      "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
+                       var->xres,var->yres,var->xres_virtual,
+                       var->yres_virtual,var->bits_per_pixel,var->pixclock,
+                       var->left_margin,var->right_margin,var->upper_margin,
+                       var->lower_margin,var->hsync_len,var->vsync_len);
+
+       htotal = (var->xres + var->left_margin + var->right_margin +
+                                                var->hsync_len) / 8 - 5;
+       hdispend = var->xres/8 - 1;
+       hsyncstart = (var->xres + var->right_margin)/8;
+       hsyncend = var->hsync_len/8;
+       hblankstart = hdispend + 1;
+       hblankend = htotal + 3; // should be htotal + 5, bios does it this way
+       preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3);
+
+       vtotal = var->yres + var->upper_margin + var->lower_margin +
+                                                var->vsync_len - 2;
+       vdispend = var->yres - 1;
+       vsyncstart = var->yres + var->lower_margin;
+       vblankstart = var->yres;
+       vblankend = vtotal; // should be vtotal + 2, but bios does it this way
+       vsyncend = var->vsync_len;
+
+       enable_mmio();          // necessary! ... check X ...
+
+       write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+
+       write3CE(GR30,8);
+
+       if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
+
+               // stretch or center ?
+
+               out8(0x3C2,0xEB);
+
+               write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+
+               if (center) {
+                       write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80);
+                       write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80);
+               }
+               else if (stretch) {
+                       write3CE(GR5D,0);
+                       write3CE(GR52,(read3CE(GR52) & 0x7C) | 1);
+                       write3CE(GR53,(read3CE(GR53) & 0x7C) | 1);
+               }
+
+       } else {
+               out8(0x3C2,0x2B);
+               write3CE(GR30,8);
+       }
+
+       //
+       // Setup CRxx regs
+       //
+
+       write3X4(CR00,htotal & 0xFF);
+       write3X4(CR01,hdispend & 0xFF);
+       write3X4(CR02,hblankstart & 0xFF);
+       write3X4(CR03,hblankend & 0x1F);
+       write3X4(CR04,hsyncstart & 0xFF);
+       write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2));
+       write3X4(CR06,vtotal & 0xFF);
+       write3X4(CR07,(vtotal & 0x100) >> 8 |
+                     (vdispend & 0x100) >> 7 |
+                     (vsyncstart & 0x100) >> 6 |
+                     (vblankstart & 0x100) >> 5 |
+                     0x10 |
+                     (vtotal & 0x200) >> 4 |
+                     (vdispend & 0x200) >> 3 |
+                     (vsyncstart & 0x200) >> 2);
+       write3X4(CR08,0);
+       write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 |  // FIX !!!
+                     ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
+       write3X4(CR0A,0);  // Init to some reasonable default
+       write3X4(CR0B,0);  // Init to some reasonable default
+       write3X4(CR0C,0);  // Offset 0
+       write3X4(CR0D,0);  // Offset 0
+       write3X4(CR0E,0);  // Init to some reasonable default
+       write3X4(CR0F,0);  // Init to some reasonable default
+       write3X4(CR10,vsyncstart & 0xFF);
+       write3X4(CR11,(vsyncend & 0x0F));
+       write3X4(CR12,vdispend & 0xFF);
+       write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF);
+       write3X4(CR14,0x40);  // double word mode
+       write3X4(CR15,vblankstart & 0xFF);
+       write3X4(CR16,vblankend & 0xFF);
+       write3X4(CR17,0xC3);
+       write3X4(CR18,0xFF);
+       //       CR19: needed for interlaced modes ... ignore it for now
+       write3X4(CR1A,0x07); // Arbitration Control Counter 1
+       write3X4(CR1B,0x07); // Arbitration Control Counter 2
+       write3X4(CR1C,0x07); // Arbitration Control Counter 3
+       write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-)
+       write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
+       //       CR1F: do not set, contains BIOS info about memsize
+       write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode
+       write3X4(CR21,0x20); // enable linear memory access
+       //       CR22: RO cpu latch readback
+       //       CR23: ???
+       //       CR24: RO AR flag state
+       //       CR25: RAMDAC rw timing, pclk buffer tristate control ????
+       //       CR26: ???
+       write3X4(CR27,(vdispend & 0x400) >> 6 |
+                     (vsyncstart & 0x400) >> 5 |
+                     (vblankstart & 0x400) >> 4 |
+                     (vtotal & 0x400) >> 3 |
+                     0x8);
+       //       CR28: ???
+       write3X4(CR29,(read3X4(CR29) & 0xCF) |
+                     ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4));
+       write3X4(CR2A,read3X4(CR2A) | 0x40);
+       write3X4(CR2B,(htotal & 0x100) >> 8 |
+                     (hdispend & 0x100) >> 7 |
+                     // (0x00 & 0x100) >> 6 |   hinterlace para bit 8 ???
+                     (hsyncstart & 0x100) >> 5 |
+                     (hblankstart & 0x100) >> 4);
+       //       CR2C: ???
+       //       CR2D: initialized in cyblafb_setup_GE()
+       write3X4(CR2F,0x92); // conservative, better signal quality
+       //       CR30: reserved
+       //       CR31: reserved
+       //       CR32: reserved
+       //       CR33: reserved
+       //       CR34: disabled in CR36
+       //       CR35: disabled in CR36
+       //       CR36: initialized in cyblafb_setup_GE
+       //       CR37: i2c, ignore for now
+       write3X4(CR38,(bpp == 8) ? 0x00 :       //
+                     (bpp == 16) ? 0x05 :      // highcolor
+                     (bpp == 24) ? 0x29 :      // packed 24bit truecolor
+                     (bpp == 32) ? 0x09 : 0);  // truecolor, 16 bit pixelbus
+       write3X4(CR39,0x01 |                    // MMIO enable
+                     (pcirb ? 0x02 : 0) | // pci read burst enable
+                     (pciwb ? 0x04 : 0)); // pci write burst enable
+       write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase
+                     (pcirr ? 0x40 : 0) | // pci read retry enable
+                     (pciwr ? 0x80 : 0)); // pci write retry enable
+       write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0);
+       write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
+       write3X4(CR58,0x82);    // Bios does this .... don't know more
+       //
+       // Setup SRxx regs
+       //
+       write3C4(SR00,3);
+       write3C4(SR01,1);       //set char clock 8 dots wide
+       write3C4(SR02,0x0F);    //enable 4 maps needed in chain4 mode
+       write3C4(SR03,0);       //no character map select
+       write3C4(SR04,0x0E);    //memory mode: ext mem, even, chain4
+
+       out8(0x3C4,0x0b);
+       in8(0x3C5);             // Set NEW mode
+       write3C4(SR0D,0x00);    // test ... check
+
+       set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
+                info->var.pixclock); //SR18,SR19
+
+       //
+       // Setup GRxx regs
+       //
+       write3CE(GR00,0x00);    // test ... check
+       write3CE(GR01,0x00);    // test ... check
+       write3CE(GR02,0x00);    // test ... check
+       write3CE(GR03,0x00);    // test ... check
+       write3CE(GR04,0x00);    // test ... check
+       write3CE(GR05,0x40);    // no CGA compat,allow 256 col
+       write3CE(GR06,0x05);    // graphics mode
+       write3CE(GR07,0x0F);    // planes?
+       write3CE(GR08,0xFF);    // test ... check
+       write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4
+       write3CE(GR20,0xC0);    // test ... check
+       write3CE(GR2F,0xA0);    // PCLK = VCLK, no skew,
+
+       //
+       // Setup ARxx regs
+       //
+       for(i = 0;i < 0x10;i++) // set AR00 .. AR0f
+               write3C0(i,i);
+       write3C0(AR10,0x41);    // graphics mode and support 256 color modes
+       write3C0(AR12,0x0F);    // planes
+       write3C0(AR13,0);       // horizontal pel panning
+       in8(0x3DA);             // reset internal flag to 3c0 index
+       out8(0x3C0,0x20);       // enable attr
+
+       //
+       // Setup hidden RAMDAC command register
+       //
+       in8(0x3C8);  // these reads are
+       in8(0x3C6);  // necessary to
+       in8(0x3C6);  // unmask the RAMDAC
+       in8(0x3C6);  // command reg, otherwise
+       in8(0x3C6);  // we would write the pixelmask reg!
+       out8(0x3C6,(bpp ==  8) ? 0x00 :         // 256 colors
+                  (bpp == 15) ? 0x10 :         //
+                  (bpp == 16) ? 0x30 :         // hicolor
+                  (bpp == 24) ? 0xD0 :         // truecolor
+                  (bpp == 32) ? 0xD0 : 0);     // truecolor
+       in8(0x3C8);
+
+       //
+       // GR31 is not mentioned in the datasheet
+       //
+       if (displaytype == DISPLAY_FP)
+               write3CE(GR31,(read3CE(GR31) & 0x8F) |
+                        ((info->var.yres > 1024) ? 0x50 :
+                        (info->var.yres >   768) ? 0x30 :
+                        (info->var.yres >   600) ? 0x20 :
+                        (info->var.yres >   480) ? 0x10 : 0));
+
+       info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
+                                     : FB_VISUAL_TRUECOLOR;
+       info->fix.line_length = info->var.xres * (bpp >> 3);
+       info->cmap.len = (bpp == 8) ? 256: 16;
+
+       //
+       // init acceleration engine
+       //
+       cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+
+       regdump(par);
+
+       return 0;
+}
+
+//========================
+//
+// Set one color register
+//
+//========================
+
+static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                            unsigned blue, unsigned transp,
+                            struct fb_info *info)
+{
+       int bpp = info->var.bits_per_pixel;
+
+       if (regno >= info->cmap.len)
+               return 1;
+
+       if (bpp == 8) {
+               out8(0x3C6,0xFF);
+               out8(0x3C8,regno);
+               out8(0x3C9,red>>10);
+               out8(0x3C9,green>>10);
+               out8(0x3C9,blue>>10);
+
+       } else if (bpp == 16)                           // RGB 565
+               ((u32*)info->pseudo_palette)[regno] =
+                       (red & 0xF800) |
+                       ((green & 0xFC00) >> 5) |
+                       ((blue & 0xF800) >> 11);
+       else if (bpp == 32)                             // ARGB 8888
+               ((u32*)info->pseudo_palette)[regno] =
+                       ((transp & 0xFF00) <<16) |
+                       ((red & 0xFF00) << 8) |
+                       ((green & 0xFF00)) |
+                       ((blue & 0xFF00)>>8);
+
+       return 0;
+}
+
+//==========================================================
+//
+// Try blanking the screen. For flat panels it does nothing
+//
+//==========================================================
+
+static int cyblafb_blank(int blank_mode, struct fb_info *info)
+{
+       unsigned char PMCont,DPMSCont;
+
+       if (displaytype == DISPLAY_FP)
+               return 0;
+
+       out8(0x83C8,0x04);              // DPMS Control
+       PMCont = in8(0x83C6) & 0xFC;
+
+       DPMSCont = read3CE(GR23) & 0xFC;
+
+       switch (blank_mode)
+       {
+       case FB_BLANK_UNBLANK:       // Screen: On, HSync: On, VSync: On
+       case FB_BLANK_NORMAL:        // Screen: Off, HSync: On, VSync: On
+               PMCont |= 0x03;
+               DPMSCont |= 0x00;
+               break;
+       case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
+               PMCont |= 0x02;
+               DPMSCont |= 0x01;
+               break;
+       case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
+               PMCont |= 0x02;
+               DPMSCont |= 0x02;
+               break;
+       case FB_BLANK_POWERDOWN:     // Screen: Off, HSync: Off, VSync: Off
+               PMCont |= 0x00;
+               DPMSCont |= 0x03;
+               break;
+       }
+
+       write3CE(GR23,DPMSCont);
+       out8(0x83C8,4);
+       out8(0x83C6,PMCont);
+       //
+       // let fbcon do a softblank for us
+       //
+       return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
+}
+
+static struct fb_ops cyblafb_ops __devinitdata = {
+       .owner  = THIS_MODULE,
+       .fb_setcolreg = cyblafb_setcolreg,
+       .fb_pan_display = cyblafb_pan_display,
+       .fb_blank = cyblafb_blank,
+       .fb_check_var = cyblafb_check_var,
+       .fb_set_par = cyblafb_set_par,
+       .fb_fillrect = cyblafb_fillrect,
+       .fb_copyarea= cyblafb_copyarea,
+       .fb_imageblit = cyblafb_imageblit,
+       .fb_cursor = soft_cursor,
+};
+
+//==========================================================================
+//
+// getstartupmode() decides about the inital video mode
+//
+// There is no reason to use modedb, a lot of video modes there would
+// need altered timings to display correctly. So I decided that it is much
+// better to provide a limited optimized set of modes plus the option of
+// using the mode in effect at startup time (might be selected using the
+// vga=??? paramter). After that the user might use fbset to select any
+// mode he likes, check_var will not try to alter geometry parameters as
+// it would be necessary otherwise.
+//
+//==========================================================================
+
+static int __devinit getstartupmode(struct fb_info *info)
+{
+       u32     htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,
+               vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend,
+               cr00,cr01,cr02,cr03,cr04,cr05,cr2b,
+               cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27,
+               cr38,
+               sr0d,sr18,sr19,
+               gr0f,
+               fi,pxclkdiv,vclkdiv,tmp,i;
+
+       struct modus {
+               int xres; int yres; int vyres; int bpp; int pxclk;
+               int left_margin; int right_margin; int upper_margin;
+               int lower_margin; int hsync_len; int vsync_len;
+       }  modedb[5] = {
+               {   0,    0, 8000, 0, 0,   0,  0,  0, 0,   0,  0},
+               { 640,  480, 3756, 0, 0, -40, 24, 17, 0, 216,  3},
+               { 800,  600, 3221, 0, 0,  96, 24, 14, 0, 136, 11},
+               {1024,  768, 2815, 0, 0, 144, 24, 29, 0, 120,  3},
+               {1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160,  3}
+       };
+
+       outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5);
+       outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5);
+       outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5);
+       outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5);
+       outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5);
+       outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5);
+       outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5);
+       outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5);
+       outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5);
+       outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5);
+       outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf);
+
+       htotal      = cr00 | (cr2b & 0x01) << 8;
+       hdispend    = cr01 | (cr2b & 0x02) << 7;
+       hblankstart = cr02 | (cr2b & 0x10) << 4;
+       hblankend   = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
+       hsyncstart  = cr04 | (cr2b & 0x08) << 5;
+       hsyncend    = cr05 & 0x1f;
+
+       modedb[0].xres = hblankstart * 8;
+       modedb[0].hsync_len = hsyncend * 8;
+       modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
+       modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
+               modedb[0].right_margin - modedb[0].hsync_len;
+
+       vtotal      = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
+                          | (cr27 & 0x80) << 3;
+       vdispend    = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
+                          | (cr27 & 0x10) << 6;
+       vsyncstart  = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
+                          | (cr27 & 0x20) << 5;
+       vsyncend    = cr11 & 0x0f;
+       vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
+                          | (cr27 & 0x40) << 4;
+       vblankend   = cr16;
+
+       modedb[0].yres         = vdispend + 1;
+       modedb[0].vsync_len    = vsyncend;
+       modedb[0].lower_margin = vsyncstart - modedb[0].yres;
+       modedb[0].upper_margin = vtotal - modedb[0].yres -
+               modedb[0].lower_margin - modedb[0].vsync_len + 2;
+
+       tmp = cr38 & 0x3c;
+       modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
+                       tmp == 8 ? 32 : 8;
+
+       fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+       pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
+       tmp = sr0d & 0x06;
+       vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
+       modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi;
+
+       if (verbosity > 0)
+               output("detected startup mode: "
+                      "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
+                      modedb[0].xres,modedb[0].yres,modedb[0].xres,
+                      modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin,
+                      modedb[0].right_margin,modedb[0].upper_margin,
+                      modedb[0].lower_margin,modedb[0].hsync_len,
+                      modedb[0].vsync_len);
+
+       //
+       // We use this goto target in case of a failed check_var. No, I really
+       // do not want to do it in another way!
+       //
+
+       tryagain:
+
+       i = (mode == NULL) ? 0 :
+           !strncmp(mode,"640x480",7) ? 1 :
+           !strncmp(mode,"800x600",7) ? 2 :
+           !strncmp(mode,"1024x768",8) ? 3 :
+           !strncmp(mode,"1280x1024",9) ? 4 : 0;
+
+       ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
+
+       if(i==0) {
+               info->var.pixclock = modedb[i].pxclk;
+               info->var.bits_per_pixel = modedb[i].bpp;
+       } else {
+               info->var.pixclock = (100000000 /
+                       ((modedb[i].left_margin + modedb[i].xres +
+                         modedb[i].right_margin + modedb[i].hsync_len
+                        ) * (
+                         modedb[i].upper_margin + modedb[i].yres +
+                         modedb[i].lower_margin + modedb[i].vsync_len
+                        ) *
+                         ref / 10000
+                       ));
+               info->var.bits_per_pixel = bpp;
+       }
+
+       info->var.left_margin = modedb[i].left_margin;
+       info->var.right_margin = modedb[i].right_margin;
+       info->var.xres = modedb[i].xres;
+       info->var.xres_virtual = modedb[i].xres;
+       info->var.xoffset = 0;
+       info->var.hsync_len = modedb[i].hsync_len;
+       info->var.upper_margin = modedb[i].upper_margin;
+       info->var.yres = modedb[i].yres;
+       info->var.yres_virtual = modedb[i].vyres;
+       info->var.yoffset = 0;
+       info->var.lower_margin = modedb[i].lower_margin;
+       info->var.vsync_len = modedb[i].vsync_len;
+       info->var.sync = 0;
+       info->var.vmode = FB_VMODE_NONINTERLACED;
+
+       if(cyblafb_check_var(&info->var,info)) {
+               // 640x480-8@75 should really never fail. One case would
+               // be fp == 1 and nativex < 640 ... give up then
+               if(i==1 && bpp == 8 && ref == 75){
+                       output("Can't find a valid mode :-(\n");
+                       return -EINVAL;
+               }
+               // Our detected mode is unlikely to fail. If it does,
+               // try 640x480-8@75 ...
+               if(i==0) {
+                       mode="640x480";
+                       bpp=8;
+                       ref=75;
+                       output("Detected mode failed check_var! "
+                              "Trying 640x480-8@75\n");
+                       goto tryagain;
+               }
+               // A specified video mode failed for some reason.
+               // Try the startup mode first
+               output("Specified mode '%s' failed check! "
+                       "Falling back to startup mode.\n",mode);
+               mode=NULL;
+               goto tryagain;
+       }
+
+       return 0;
+
+}
+
+//========================================================
+//
+// Detect activated memory size. Undefined values require
+// memsize parameter.
+//
+//========================================================
+
+static unsigned int __devinit get_memsize(void)
+{
+       unsigned char tmp;
+       unsigned int k;
+
+       if (memsize)
+               k = memsize * Kb;
+       else {
+               tmp = read3X4(CR1F) & 0x0F;
+               switch (tmp) {
+                       case 0x03: k = 1 * Mb; break;
+                       case 0x07: k = 2 * Mb; break;
+                       case 0x0F: k = 4 * Mb; break;
+                       case 0x04: k = 8 * Mb; break;
+                       default:
+                               k = 1 * Mb;
+                               output("Unknown memory size code %x in CR1F."
+                                      " We default to 1 Mb for now, please"
+                                      " do provide a memsize parameter!\n",
+                                      tmp);
+               }
+       }
+
+       if (verbosity > 0)
+               output("framebuffer size = %d Kb\n",k/Kb);
+       return k;
+}
+
+//=========================================================
+//
+// Detect if a flat panel monitor connected to the special
+// interface is active. Override is possible by fp and crt
+// parameters.
+//
+//=========================================================
+
+static unsigned int __devinit get_displaytype(void)
+{
+       if (fp)
+               return DISPLAY_FP;
+       if (crt)
+               return DISPLAY_CRT;
+       return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+}
+
+//=====================================
+//
+// Get native resolution of flat panel
+//
+//=====================================
+
+static int __devinit get_nativex(void)
+{
+       int x,y,tmp;
+
+       if (nativex)
+               return nativex;
+
+       tmp = (read3CE(GR52) >> 4) & 3;
+
+       switch (tmp) {
+               case 0:  x = 1280; y = 1024; break;
+               case 2:  x = 1024; y = 768;  break;
+               case 3:  x = 800;  y = 600;  break;
+               case 4:  x = 1400; y = 1050; break;
+               case 1:
+               default: x = 640;  y = 480;  break;
+       }
+
+       if (verbosity > 0)
+               output("%dx%d flat panel found\n",x,y);
+       return x;
+}
+
+static int __devinit cybla_pci_probe(struct pci_dev * dev,
+                                    const struct pci_device_id * id)
+{
+       struct fb_info *info;
+       struct cyblafb_par *par;
+
+       info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev);
+
+       if (!info)
+               goto errout_alloc;
+
+       par = info->par;
+       par->ops = cyblafb_ops;
+
+       info->fix = cyblafb_fix;
+       info->fbops = &par->ops;
+       info->fix = cyblafb_fix;
+
+       if (pci_enable_device(dev)) {
+               output("could not enable device!\n");
+               goto errout_enable;
+       }
+
+       // might already be requested by vga console or vesafb,
+       // so we do care about success
+       request_region(0x3c0,32,"cyblafb");
+
+       //
+       // Graphics Engine Registers
+       //
+       request_region(GEBase,0x100,"cyblafb");
+
+       regdump(par);
+
+       enable_mmio();
+
+       // setup MMIO region
+       info->fix.mmio_start = pci_resource_start(dev,1);
+       info->fix.mmio_len = 0x20000;
+
+       if (!request_mem_region(info->fix.mmio_start,
+                               info->fix.mmio_len,"cyblafb")) {
+               output("request_mem_region failed for mmio region!\n");
+               goto errout_mmio_reqmem;
+       }
+
+       io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
+
+       if (!io_virt) {
+               output("ioremap failed for mmio region\n");
+               goto errout_mmio_remap;
+       }
+
+       // setup framebuffer memory ... might already be requested
+       // by vesafb. Not to fail in case of an unsuccessful request
+       // is useful for the development cycle
+       info->fix.smem_start = pci_resource_start(dev,0);
+       info->fix.smem_len = get_memsize();
+
+       if (!request_mem_region(info->fix.smem_start,
+                               info->fix.smem_len,"cyblafb")) {
+               output("request_mem_region failed for smem region!\n");
+               if (!vesafb)
+                       goto errout_smem_req;
+       }
+
+       info->screen_base = ioremap_nocache(info->fix.smem_start,
+                                           info->fix.smem_len);
+
+       if (!info->screen_base) {
+               output("ioremap failed for smem region\n");
+               goto errout_smem_remap;
+       }
+
+       displaytype = get_displaytype();
+
+       if(displaytype == DISPLAY_FP)
+               nativex = get_nativex();
+
+       //
+       // FBINFO_HWACCEL_YWRAP    .... does not work (could be made to work?)
+       // FBINFO_PARTIAL_PAN_OK   .... is not ok
+       // FBINFO_READS_FAST       .... is necessary for optimal scrolling
+       //
+       info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN
+                     | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT
+                     | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST;
+
+       info->pseudo_palette = par->pseudo_pal;
+
+       if(getstartupmode(info))
+               goto errout_findmode;
+
+       fb_alloc_cmap(&info->cmap,256,0);
+
+       if (register_framebuffer(info)) {
+               output("Could not register CyBla framebuffer\n");
+               goto errout_register;
+       }
+
+       pci_set_drvdata(dev,info);
+
+       //
+       // normal exit and error paths
+       //
+
+       return 0;
+
+ errout_register:
+ errout_findmode:
+       iounmap(info->screen_base);
+ errout_smem_remap:
+       release_mem_region(info->fix.smem_start,
+                          info->fix.smem_len);
+ errout_smem_req:
+       iounmap(io_virt);
+ errout_mmio_remap:
+       release_mem_region(info->fix.mmio_start,
+                          info->fix.mmio_len);
+ errout_mmio_reqmem:
+//     release_region(0x3c0,32);
+ errout_enable:
+       framebuffer_release(info);
+ errout_alloc:
+       output("CyblaFB version %s aborting init.\n",VERSION);
+       return -ENODEV;
+}
+
+static void __devexit cybla_pci_remove(struct pci_dev *dev)
+{
+       struct fb_info *info = pci_get_drvdata(dev);
+
+       unregister_framebuffer(info);
+       iounmap(io_virt);
+       iounmap(info->screen_base);
+       release_mem_region(info->fix.smem_start,info->fix.smem_len);
+       release_mem_region(info->fix.mmio_start,info->fix.mmio_len);
+       fb_dealloc_cmap(&info->cmap);
+       framebuffer_release(info);
+       output("CyblaFB version %s normal exit.\n",VERSION);
+}
+
+//
+// List of boards that we are trying to support
+//
+static struct pci_device_id cybla_devices[] = {
+       {PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci,cybla_devices);
+
+static struct pci_driver cyblafb_pci_driver = {
+       .name           = "cyblafb",
+       .id_table       = cybla_devices,
+       .probe          = cybla_pci_probe,
+       .remove         = __devexit_p(cybla_pci_remove)
+};
+
+//=============================================================
+//
+// kernel command line example:
+//
+//     video=cyblafb:1280x1024,bpp=16,ref=50 ...
+//
+// modprobe command line example:
+//
+//     modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ...
+//
+//=============================================================
+
+static int __devinit cyblafb_init(void)
+{
+#ifndef MODULE
+       char *options = NULL;
+       char *opt;
+
+       if (fb_get_options("cyblafb",&options))
+               return -ENODEV;
+
+       if (options && *options)
+               while((opt = strsep(&options,",")) != NULL ) {
+                       if (!*opt) continue;
+                       else if (!strncmp(opt,"bpp=",4))
+                               bpp = simple_strtoul(opt+4,NULL,0);
+                       else if (!strncmp(opt,"ref=",4))
+                               ref = simple_strtoul(opt+4,NULL,0);
+                       else if (!strncmp(opt,"fp",2))
+                               displaytype = DISPLAY_FP;
+                       else if (!strncmp(opt,"crt",3))
+                               displaytype = DISPLAY_CRT;
+                       else if (!strncmp(opt,"nativex=",8))
+                               nativex = simple_strtoul(opt+8,NULL,0);
+                       else if (!strncmp(opt,"center",6))
+                               center = 1;
+                       else if (!strncmp(opt,"stretch",7))
+                               stretch = 1;
+                       else if (!strncmp(opt,"pciwb=",6))
+                               pciwb = simple_strtoul(opt+6,NULL,0);
+                       else if (!strncmp(opt,"pcirb=",6))
+                               pcirb = simple_strtoul(opt+6,NULL,0);
+                       else if (!strncmp(opt,"pciwr=",6))
+                               pciwr = simple_strtoul(opt+6,NULL,0);
+                       else if (!strncmp(opt,"pcirr=",6))
+                               pcirr = simple_strtoul(opt+6,NULL,0);
+                       else if (!strncmp(opt,"memsize=",8))
+                               memsize = simple_strtoul(opt+8,NULL,0);
+                       else if (!strncmp(opt,"verbosity=",10))
+                               verbosity = simple_strtoul(opt+10,NULL,0);
+                       else if (!strncmp(opt,"vesafb",6))
+                               vesafb = 1;
+                       else
+                               mode = opt;
+               }
+#endif
+       output("CyblaFB version %s initializing\n",VERSION);
+       return pci_module_init(&cyblafb_pci_driver);
+}
+
+static void __exit cyblafb_exit(void)
+{
+       pci_unregister_driver(&cyblafb_pci_driver);
+}
+
+module_init(cyblafb_init);
+module_exit(cyblafb_exit);
+
+MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>");
+MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
new file mode 100644 (file)
index 0000000..cfa61b5
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * linux/drivers/video/fbcvt.c - VESA(TM) Coordinated Video Timings
+ *
+ * Copyright (C) 2005 Antonino Daplas <adaplas@pol.net>
+ *
+ *      Based from the VESA(TM) Coordinated Video Timing Generator by
+ *      Graham Loveridge April 9, 2003 available at
+ *      http://www.vesa.org/public/CVT/CVTd6r1.xls
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/fb.h>
+
+#define FB_CVT_CELLSIZE               8
+#define FB_CVT_GTF_C                 40
+#define FB_CVT_GTF_J                 20
+#define FB_CVT_GTF_K                128
+#define FB_CVT_GTF_M                600
+#define FB_CVT_MIN_VSYNC_BP         550
+#define FB_CVT_MIN_VPORCH             3
+#define FB_CVT_MIN_BPORCH             6
+
+#define FB_CVT_RB_MIN_VBLANK        460
+#define FB_CVT_RB_HBLANK            160
+#define FB_CVT_RB_V_FPORCH            3
+
+#define FB_CVT_FLAG_REDUCED_BLANK 1
+#define FB_CVT_FLAG_MARGINS       2
+#define FB_CVT_FLAG_INTERLACED    4
+
+struct fb_cvt_data {
+       u32 xres;
+       u32 yres;
+       u32 refresh;
+       u32 f_refresh;
+       u32 pixclock;
+       u32 hperiod;
+       u32 hblank;
+       u32 hfreq;
+       u32 htotal;
+       u32 vtotal;
+       u32 vsync;
+       u32 hsync;
+       u32 h_front_porch;
+       u32 h_back_porch;
+       u32 v_front_porch;
+       u32 v_back_porch;
+       u32 h_margin;
+       u32 v_margin;
+       u32 interlace;
+       u32 aspect_ratio;
+       u32 active_pixels;
+       u32 flags;
+       u32 status;
+};
+
+static int fb_cvt_vbi_tab[] = {
+       4,        /* 4:3      */
+       5,        /* 16:9     */
+       6,        /* 16:10    */
+       7,        /* 5:4      */
+       7,        /* 15:9     */
+       8,        /* reserved */
+       9,        /* reserved */
+       10        /* custom   */
+};
+
+/* returns hperiod * 1000 */
+static u32 fb_cvt_hperiod(struct fb_cvt_data *cvt)
+{
+       u32 num = 1000000000/cvt->f_refresh;
+       u32 den;
+
+       if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+               num -= FB_CVT_RB_MIN_VBLANK * 1000;
+               den = 2 * (cvt->yres/cvt->interlace + 2 * cvt->v_margin);
+       } else {
+               num -= FB_CVT_MIN_VSYNC_BP * 1000;
+               den = 2 * (cvt->yres/cvt->interlace + cvt->v_margin * 2
+                          + FB_CVT_MIN_VPORCH + cvt->interlace/2);
+       }
+
+       return 2 * (num/den);
+}
+
+/* returns ideal duty cycle * 1000 */
+static u32 fb_cvt_ideal_duty_cycle(struct fb_cvt_data *cvt)
+{
+       u32 c_prime = (FB_CVT_GTF_C - FB_CVT_GTF_J) *
+               (FB_CVT_GTF_K) + 256 * FB_CVT_GTF_J;
+       u32 m_prime = (FB_CVT_GTF_K * FB_CVT_GTF_M);
+       u32 h_period_est = cvt->hperiod;
+
+       return (1000 * c_prime  - ((m_prime * h_period_est)/1000))/256;
+}
+
+static u32 fb_cvt_hblank(struct fb_cvt_data *cvt)
+{
+       u32 hblank = 0;
+
+       if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+               hblank = FB_CVT_RB_HBLANK;
+       else {
+               u32 ideal_duty_cycle = fb_cvt_ideal_duty_cycle(cvt);
+               u32 active_pixels = cvt->active_pixels;
+
+               if (ideal_duty_cycle < 20000)
+                       hblank = (active_pixels * 20000)/
+                               (100000 - 20000);
+               else {
+                       hblank = (active_pixels * ideal_duty_cycle)/
+                               (100000 - ideal_duty_cycle);
+               }
+       }
+
+       hblank &= ~((2 * FB_CVT_CELLSIZE) - 1);
+
+       return hblank;
+}
+
+static u32 fb_cvt_hsync(struct fb_cvt_data *cvt)
+{
+       u32 hsync;
+
+       if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+               hsync = 32;
+       else
+               hsync = (FB_CVT_CELLSIZE * cvt->htotal)/100;
+
+       hsync &= ~(FB_CVT_CELLSIZE - 1);
+       return hsync;
+}
+
+static u32 fb_cvt_vbi_lines(struct fb_cvt_data *cvt)
+{
+       u32 vbi_lines, min_vbi_lines, act_vbi_lines;
+
+       if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+               vbi_lines = (1000 * FB_CVT_RB_MIN_VBLANK)/cvt->hperiod + 1;
+               min_vbi_lines =  FB_CVT_RB_V_FPORCH + cvt->vsync +
+                       FB_CVT_MIN_BPORCH;
+
+       } else {
+               vbi_lines = (FB_CVT_MIN_VSYNC_BP * 1000)/cvt->hperiod + 1 +
+                        FB_CVT_MIN_VPORCH;
+               min_vbi_lines = cvt->vsync + FB_CVT_MIN_BPORCH +
+                       FB_CVT_MIN_VPORCH;
+       }
+
+       if (vbi_lines < min_vbi_lines)
+               act_vbi_lines = min_vbi_lines;
+       else
+               act_vbi_lines = vbi_lines;
+
+       return act_vbi_lines;
+}
+
+static u32 fb_cvt_vtotal(struct fb_cvt_data *cvt)
+{
+       u32 vtotal = cvt->yres/cvt->interlace;
+
+       vtotal += 2 * cvt->v_margin + cvt->interlace/2 + fb_cvt_vbi_lines(cvt);
+       vtotal |= cvt->interlace/2;
+
+       return vtotal;
+}
+
+static u32 fb_cvt_pixclock(struct fb_cvt_data *cvt)
+{
+       u32 pixclock;
+
+       if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+               pixclock = (cvt->f_refresh * cvt->vtotal * cvt->htotal)/1000;
+       else
+               pixclock = (cvt->htotal * 1000000)/cvt->hperiod;
+
+       pixclock /= 250;
+       pixclock *= 250;
+       pixclock *= 1000;
+
+       return pixclock;
+}
+
+static u32 fb_cvt_aspect_ratio(struct fb_cvt_data *cvt)
+{
+       u32 xres = cvt->xres;
+       u32 yres = cvt->yres;
+       u32 aspect = -1;
+
+       if (xres == (yres * 4)/3 && !((yres * 4) % 3))
+               aspect = 0;
+       else if (xres == (yres * 16)/9 && !((yres * 16) % 9))
+               aspect = 1;
+       else if (xres == (yres * 16)/10 && !((yres * 16) % 10))
+               aspect = 2;
+       else if (xres == (yres * 5)/4 && !((yres * 5) % 4))
+               aspect = 3;
+       else if (xres == (yres * 15)/9 && !((yres * 15) % 9))
+               aspect = 4;
+       else {
+               printk(KERN_INFO "fbcvt: Aspect ratio not CVT "
+                      "standard\n");
+               aspect = 7;
+               cvt->status = 1;
+       }
+
+       return aspect;
+}
+
+static void fb_cvt_print_name(struct fb_cvt_data *cvt)
+{
+       u32 pixcount, pixcount_mod;
+       int cnt = 255, offset = 0, read = 0;
+       u8 *buf = kmalloc(256, GFP_KERNEL);
+
+       if (!buf)
+               return;
+
+       memset(buf, 0, 256);
+       pixcount = (cvt->xres * (cvt->yres/cvt->interlace))/1000000;
+       pixcount_mod = (cvt->xres * (cvt->yres/cvt->interlace)) % 1000000;
+       pixcount_mod /= 1000;
+
+       read = snprintf(buf+offset, cnt, "fbcvt: %dx%d@%d: CVT Name - ",
+                       cvt->xres, cvt->yres, cvt->refresh);
+       offset += read;
+       cnt -= read;
+
+       if (cvt->status)
+               snprintf(buf+offset, cnt, "Not a CVT standard - %d.%03d Mega "
+                        "Pixel Image\n", pixcount, pixcount_mod);
+       else {
+               if (pixcount) {
+                       read = snprintf(buf+offset, cnt, "%d", pixcount);
+                       cnt -= read;
+                       offset += read;
+               }
+
+               read = snprintf(buf+offset, cnt, ".%03dM", pixcount_mod);
+               cnt -= read;
+               offset += read;
+
+               if (cvt->aspect_ratio == 0)
+                       read = snprintf(buf+offset, cnt, "3");
+               else if (cvt->aspect_ratio == 3)
+                       read = snprintf(buf+offset, cnt, "4");
+               else if (cvt->aspect_ratio == 1 || cvt->aspect_ratio == 4)
+                       read = snprintf(buf+offset, cnt, "9");
+               else if (cvt->aspect_ratio == 2)
+                       read = snprintf(buf+offset, cnt, "A");
+               else
+                       read = 0;
+               cnt -= read;
+               offset += read;
+
+               if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK) {
+                       read = snprintf(buf+offset, cnt, "-R");
+                       cnt -= read;
+                       offset += read;
+               }
+       }
+
+       printk(KERN_INFO "%s\n", buf);
+       kfree(buf);
+}
+
+static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt,
+                                  struct fb_videomode *mode)
+{
+       mode->refresh = cvt->f_refresh;
+       mode->pixclock = KHZ2PICOS(cvt->pixclock/1000);
+       mode->left_margin = cvt->h_front_porch;
+       mode->right_margin = cvt->h_back_porch;
+       mode->hsync_len = cvt->hsync;
+       mode->upper_margin = cvt->v_front_porch;
+       mode->lower_margin = cvt->v_back_porch;
+       mode->vsync_len = cvt->vsync;
+
+       mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+
+       if (cvt->flags & FB_CVT_FLAG_REDUCED_BLANK)
+               mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+       else
+               mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+}
+
+/*
+ * fb_find_mode_cvt - calculate mode using VESA(TM) CVT
+ * @mode: pointer to fb_videomode; xres, yres, refresh and vmode must be
+ *        pre-filled with the desired values
+ * @margins: add margin to calculation (1.8% of xres and yres)
+ * @rb: compute with reduced blanking (for flatpanels)
+ *
+ * RETURNS:
+ * 0 for success
+ * @mode is filled with computed values.  If interlaced, the refresh field
+ * will be filled with the field rate (2x the frame rate)
+ *
+ * DESCRIPTION:
+ * Computes video timings using VESA(TM) Coordinated Video Timings
+ */
+int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb)
+{
+       struct fb_cvt_data cvt;
+
+       memset(&cvt, 0, sizeof(cvt));
+
+       if (margins)
+           cvt.flags |= FB_CVT_FLAG_MARGINS;
+
+       if (rb)
+           cvt.flags |= FB_CVT_FLAG_REDUCED_BLANK;
+
+       if (mode->vmode & FB_VMODE_INTERLACED)
+           cvt.flags |= FB_CVT_FLAG_INTERLACED;
+
+       cvt.xres = mode->xres;
+       cvt.yres = mode->yres;
+       cvt.refresh = mode->refresh;
+       cvt.f_refresh = cvt.refresh;
+       cvt.interlace = 1;
+
+       if (!cvt.xres || !cvt.yres || !cvt.refresh) {
+               printk(KERN_INFO "fbcvt: Invalid input parameters\n");
+               return 1;
+       }
+
+       if (!(cvt.refresh == 50 || cvt.refresh == 60 || cvt.refresh == 70 ||
+             cvt.refresh == 85)) {
+               printk(KERN_INFO "fbcvt: Refresh rate not CVT "
+                      "standard\n");
+               cvt.status = 1;
+       }
+
+       cvt.xres &= ~(FB_CVT_CELLSIZE - 1);
+
+       if (cvt.flags & FB_CVT_FLAG_INTERLACED) {
+               cvt.interlace = 2;
+               cvt.f_refresh *= 2;
+       }
+
+       if (cvt.flags & FB_CVT_FLAG_REDUCED_BLANK) {
+               if (cvt.refresh != 60) {
+                       printk(KERN_INFO "fbcvt: 60Hz refresh rate "
+                              "advised for reduced blanking\n");
+                       cvt.status = 1;
+               }
+       }
+
+       if (cvt.flags & FB_CVT_FLAG_MARGINS) {
+               cvt.h_margin = (cvt.xres * 18)/1000;
+               cvt.h_margin &= ~(FB_CVT_CELLSIZE - 1);
+               cvt.v_margin = ((cvt.yres/cvt.interlace)* 18)/1000;
+       }
+
+       cvt.aspect_ratio = fb_cvt_aspect_ratio(&cvt);
+       cvt.active_pixels = cvt.xres + 2 * cvt.h_margin;
+       cvt.hperiod = fb_cvt_hperiod(&cvt);
+       cvt.vsync = fb_cvt_vbi_tab[cvt.aspect_ratio];
+       cvt.vtotal = fb_cvt_vtotal(&cvt);
+       cvt.hblank = fb_cvt_hblank(&cvt);
+       cvt.htotal = cvt.active_pixels + cvt.hblank;
+       cvt.hsync = fb_cvt_hsync(&cvt);
+       cvt.pixclock = fb_cvt_pixclock(&cvt);
+       cvt.hfreq = cvt.pixclock/cvt.htotal;
+       cvt.h_back_porch = cvt.hblank/2 + cvt.h_margin;
+       cvt.h_front_porch = cvt.hblank - cvt.hsync - cvt.h_back_porch +
+               2 * cvt.h_margin;
+       cvt.v_back_porch = 3 + cvt.v_margin;
+       cvt.v_front_porch = cvt.vtotal - cvt.yres/cvt.interlace -
+           cvt.v_back_porch - cvt.vsync;
+       fb_cvt_print_name(&cvt);
+       fb_cvt_convert_to_mode(&cvt, mode);
+
+       return 0;
+}
+EXPORT_SYMBOL(fb_find_mode_cvt);
index 4ff853fbe0bea8352bf6df8346af90d613b06031..70be7009f8afc6af1fb7712c5ca21d17e9926f32 100644 (file)
@@ -62,16 +62,26 @@ int num_registered_fb;
  * Helpers
  */
 
-int fb_get_color_depth(struct fb_var_screeninfo *var)
+int fb_get_color_depth(struct fb_var_screeninfo *var,
+                      struct fb_fix_screeninfo *fix)
 {
-       if (var->green.length == var->blue.length &&
-           var->green.length == var->red.length &&
-           !var->green.offset && !var->blue.offset &&
-           !var->red.offset)
-               return var->green.length;
-       else
-               return (var->green.length + var->red.length +
-                       var->blue.length);
+       int depth = 0;
+
+       if (fix->visual == FB_VISUAL_MONO01 ||
+           fix->visual == FB_VISUAL_MONO10)
+               depth = 1;
+       else {
+               if (var->green.length == var->blue.length &&
+                   var->green.length == var->red.length &&
+                   var->green.offset == var->blue.offset &&
+                   var->green.offset == var->red.offset)
+                       depth = var->green.length;
+               else
+                       depth = var->green.length + var->red.length +
+                               var->blue.length;
+       }
+
+       return depth;
 }
 EXPORT_SYMBOL(fb_get_color_depth);
 
@@ -80,15 +90,7 @@ EXPORT_SYMBOL(fb_get_color_depth);
  */
 void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
 {
-       int i, j;
-
-       for (i = height; i--; ) {
-               /* s_pitch is a few bytes at the most, memcpy is suboptimal */
-               for (j = 0; j < s_pitch; j++)
-                       dst[j] = src[j];
-               src += s_pitch;
-               dst += d_pitch;
-       }
+       __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
 }
 EXPORT_SYMBOL(fb_pad_aligned_buffer);
 
@@ -249,13 +251,18 @@ static void fb_set_logo(struct fb_info *info,
                               const struct linux_logo *logo, u8 *dst,
                               int depth)
 {
-       int i, j, k, fg = 1;
+       int i, j, k;
        const u8 *src = logo->data;
-       u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+       u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+       u8 fg = 1, d;
 
-       if (fb_get_color_depth(&info->var) == 3)
+       if (fb_get_color_depth(&info->var, &info->fix) == 3)
                fg = 7;
 
+       if (info->fix.visual == FB_VISUAL_MONO01 ||
+           info->fix.visual == FB_VISUAL_MONO10)
+               fg = ~((u8) (0xfff << info->var.green.length));
+
        switch (depth) {
        case 4:
                for (i = 0; i < logo->height; i++)
@@ -318,7 +325,7 @@ static struct logo_data {
 
 int fb_prepare_logo(struct fb_info *info)
 {
-       int depth = fb_get_color_depth(&info->var);
+       int depth = fb_get_color_depth(&info->var, &info->fix);
 
        memset(&fb_logo, 0, sizeof(struct logo_data));
 
@@ -684,11 +691,13 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 
                        if (!err && (flags & FBINFO_MISC_USEREVENT)) {
                                struct fb_event event;
+                               int evnt = (var->activate & FB_ACTIVATE_ALL) ?
+                                       FB_EVENT_MODE_CHANGE_ALL :
+                                       FB_EVENT_MODE_CHANGE;
 
                                info->flags &= ~FBINFO_MISC_USEREVENT;
                                event.info = info;
-                               notifier_call_chain(&fb_notifier_list,
-                                                   FB_EVENT_MODE_CHANGE,
+                               notifier_call_chain(&fb_notifier_list, evnt,
                                                    &event);
                        }
                }
@@ -1012,6 +1021,7 @@ register_framebuffer(struct fb_info *fb_info)
 {
        int i;
        struct fb_event event;
+       struct fb_videomode mode;
 
        if (num_registered_fb == FB_MAX)
                return -ENXIO;
@@ -1042,16 +1052,11 @@ register_framebuffer(struct fb_info *fb_info)
        }       
        fb_info->pixmap.offset = 0;
 
-       if (!fb_info->modelist.prev ||
-           !fb_info->modelist.next ||
-           list_empty(&fb_info->modelist)) {
-               struct fb_videomode mode;
-
+       if (!fb_info->modelist.prev || !fb_info->modelist.next)
                INIT_LIST_HEAD(&fb_info->modelist);
-               fb_var_to_videomode(&mode, &fb_info->var);
-               fb_add_videomode(&mode, &fb_info->modelist);
-       }
 
+       fb_var_to_videomode(&mode, &fb_info->var);
+       fb_add_videomode(&mode, &fb_info->modelist);
        registered_fb[i] = fb_info;
 
        devfs_mk_cdev(MKDEV(FB_MAJOR, i),
index c2718bb949493bc8fb6a61a7e0ef94fd281650fb..713226cdf3c6b7a7ce0a247447d1909d05e57396 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/tty.h>
 #include <linux/fb.h>
 #include <linux/module.h>
+#include <video/edid.h>
 #ifdef CONFIG_PPC_OF
 #include <linux/pci.h>
 #include <asm/prom.h>
@@ -313,11 +314,13 @@ static int edid_is_monitor_block(unsigned char *block)
                return 0;
 }
 
-static void calc_mode_timings(int xres, int yres, int refresh, struct fb_videomode *mode)
+static void calc_mode_timings(int xres, int yres, int refresh,
+                             struct fb_videomode *mode)
 {
        struct fb_var_screeninfo var;
        struct fb_info info;
        
+       memset(&var, 0, sizeof(struct fb_var_screeninfo));
        var.xres = xres;
        var.yres = yres;
        fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 
@@ -1251,9 +1254,41 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
                -EINVAL : 0;
 }
 
+#if defined(__i386__)
+#include <linux/pci.h>
+
+/*
+ * We need to ensure that the EDID block is only returned for
+ * the primary graphics adapter.
+ */
+
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+       struct pci_dev *dev = NULL;
+       struct resource *res = NULL;
+       unsigned char *edid = NULL;
+
+       if (device)
+               dev = to_pci_dev(device);
+
+       if (dev)
+               res = &dev->resource[PCI_ROM_RESOURCE];
+
+       if (res && res->flags & IORESOURCE_ROM_SHADOW)
+               edid = edid_info.dummy;
+
+       return edid;
+}
+#else
+const unsigned char *fb_firmware_edid(struct device *device)
+{
+       return NULL;
+}
+#endif /* _i386_ */
+
 EXPORT_SYMBOL(fb_parse_edid);
 EXPORT_SYMBOL(fb_edid_to_monspecs);
-
+EXPORT_SYMBOL(fb_firmware_edid);
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
 EXPORT_SYMBOL(fb_destroy_modedb);
index b075fd02de31176a7ac872d7597eba408e6784fc..5a9b89c3831b1f7e254be8e047a24a2b4be3f904 100644 (file)
@@ -3,15 +3,13 @@
 #
 config FB_GEODE
        bool "AMD Geode family framebuffer support (EXPERIMENTAL)"
-       default n
-       depends on FB && EXPERIMENTAL && X86
+       depends on FB && PCI && EXPERIMENTAL && X86
        ---help---
          Say 'Y' here to allow you to select framebuffer drivers for
          the AMD Geode family of processors.
 
 config FB_GEODE_GX1
        tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
-       default n
        depends on FB_GEODE && EXPERIMENTAL
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
@@ -21,9 +19,7 @@ config FB_GEODE_GX1
          Framebuffer driver for the display controller integrated into the
          AMD Geode GX1 processor.
 
-         This driver is also available as a module ( = code which can be
-         inserted and removed from the running kernel whenever you want). The
-         module will be called gx1fb. If you want to compile it as a module,
-         say M here and read <file:Documentation/modules.txt>.
+         To compile this driver as a module, choose M here: the module will be
+         called gx1fb.
 
          If unsure, say N.
index f4983879fcc4b60a25aeeb203b0e0d8a2fde2334..926d53eeb54952c48ea41dd787149c72fb87ea5c 100644 (file)
@@ -22,7 +22,7 @@
 #include "geodefb.h"
 #include "display_gx1.h"
 
-static spinlock_t gx1_conf_reg_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(gx1_conf_reg_lock);
 
 static u8 gx1_read_conf_reg(u8 reg)
 {
index b7bac0a526b3814bd6ac5edac31215ce855fc6ad..ae04820e0c5773d74d46671dc79c69c86434516a 100644 (file)
@@ -29,7 +29,6 @@ struct geodefb_par {
        int enable_crt;
        int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
        int panel_y;
-       struct pci_dev *vid_dev;
        void __iomem *dc_regs;
        void __iomem *vid_regs;
        struct geode_dc_ops  *dc_ops;
index 83830d24bcdaa352ea7cb98570a48dfd47a12e3f..74a5fca86b8ac505c32f9041523fbe04c0082e9f 100644 (file)
@@ -30,6 +30,62 @@ static char mode_option[32] = "640x480-16@60";
 static int  crt_option = 1;
 static char panel_option[32] = "";
 
+/* Modes relevant to the GX1 (taken from modedb.c) */
+static const struct fb_videomode __initdata gx1_modedb[] = {
+       /* 640x480-60 VESA */
+       { NULL, 60, 640, 480, 39682,  48, 16, 33, 10, 96, 2,
+         0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 640x480-75 VESA */
+       { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+         0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 640x480-85 VESA */
+       { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+         0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 800x600-60 VESA */
+       { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 800x600-75 VESA */
+       { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 800x600-85 VESA */
+       { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1024x768-60 VESA */
+       { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+         0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1024x768-75 VESA */
+       { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1024x768-85 VESA */
+       { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1280x960-60 VESA */
+       { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1280x960-85 VESA */
+       { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1280x1024-60 VESA */
+       { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1280x1024-75 VESA */
+       { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+       /* 1280x1024-85 VESA */
+       { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+         FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
 static int gx1_line_delta(int xres, int bpp)
 {
        int line_delta = xres * (bpp >> 3);
@@ -47,8 +103,6 @@ static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct geodefb_par *par = info->par;
 
-       printk(KERN_DEBUG "%s()\n", __FUNCTION__);
-
        /* Maximum resolution is 1280x1024. */
        if (var->xres > 1280 || var->yres > 1024)
                return -EINVAL;
@@ -146,40 +200,48 @@ static int gx1fb_blank(int blank_mode, struct fb_info *info)
        return par->vid_ops->blank_display(info, blank_mode);
 }
 
-static int __init gx1fb_map_video_memory(struct fb_info *info)
+static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
 {
        struct geodefb_par *par = info->par;
        unsigned gx_base;
        int fb_len;
+       int ret;
 
        gx_base = gx1_gx_base();
        if (!gx_base)
                return -ENODEV;
 
-       par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX,
-                                     PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL);
-       if (!par->vid_dev)
-               return -ENODEV;
+       ret = pci_enable_device(dev);
+       if (ret < 0)
+               return ret;
 
-       par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1),
-                               pci_resource_len(par->vid_dev, 1));
+       ret = pci_request_region(dev, 1, "gx1fb (video)");
+       if (ret < 0)
+               return ret;
+       par->vid_regs = ioremap(pci_resource_start(dev, 1),
+                               pci_resource_len(dev, 1));
        if (!par->vid_regs)
                return -ENOMEM;
 
+       if (!request_mem_region(gx_base + 0x8300, 0x100, "gx1fb (display controller)"))
+               return -EBUSY;
        par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
        if (!par->dc_regs)
                return -ENOMEM;
 
-       info->fix.smem_start = gx_base + 0x800000;
+       ret = pci_request_region(dev, 0, "gx1fb (frame buffer)");
+       if (ret < 0 )
+               return -EBUSY;
        if ((fb_len = gx1_frame_buffer_size()) < 0)
                return -ENOMEM;
+       info->fix.smem_start = pci_resource_start(dev, 0);
        info->fix.smem_len = fb_len;
        info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
        if (!info->screen_base)
                return -ENOMEM;
 
-       printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n",
-              info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start);
+       dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
+                info->fix.smem_len / 1024, info->fix.smem_start);
 
        return 0;
 }
@@ -216,13 +278,13 @@ static struct fb_ops gx1fb_ops = {
        .fb_cursor      = soft_cursor,
 };
 
-static struct fb_info * __init gx1fb_init_fbinfo(void)
+static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
 {
-       struct fb_info *info;
        struct geodefb_par *par;
+       struct fb_info *info;
 
        /* Alloc enough space for the pseudo palette. */
-       info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, NULL);
+       info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev);
        if (!info)
                return NULL;
 
@@ -255,47 +317,37 @@ static struct fb_info * __init gx1fb_init_fbinfo(void)
        /* CRT and panel options */
        par->enable_crt = crt_option;
        if (parse_panel_option(info) < 0)
-               printk(KERN_WARNING "%s: invalid 'panel' option -- disabling flat panel\n",
-                      info->fix.id);
+               printk(KERN_WARNING "gx1fb: invalid 'panel' option -- disabling flat panel\n");
        if (!par->panel_x)
                par->enable_crt = 1; /* fall back to CRT if no panel is specified */
 
        return info;
 }
 
-
-static struct fb_info *gx1fb_info;
-
-static int __init gx1fb_init(void)
+static int __init gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+       struct geodefb_par *par;
        struct fb_info *info;
-        struct geodefb_par *par;
        int ret;
 
-#ifndef MODULE
-       if (fb_get_options("gx1fb", NULL))
-               return -ENODEV;
-#endif
-
-       info = gx1fb_init_fbinfo();
+       info = gx1fb_init_fbinfo(&pdev->dev);
        if (!info)
                return -ENOMEM;
-       gx1fb_info = info;
-
        par = info->par;
 
        /* GX1 display controller and CS5530 video device */
        par->dc_ops  = &gx1_dc_ops;
        par->vid_ops = &cs5530_vid_ops;
 
-       if ((ret = gx1fb_map_video_memory(info)) < 0) {
-               printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id);
+       if ((ret = gx1fb_map_video_memory(info, pdev)) < 0) {
+               dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
                goto err;
        }
 
-       ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
+       ret = fb_find_mode(&info->var, info, mode_option,
+                          gx1_modedb, ARRAY_SIZE(gx1_modedb), NULL, 16);
        if (ret == 0 || ret == 4) {
-               printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id);
+               dev_err(&pdev->dev, "could not find valid video mode\n");
                ret = -EINVAL;
                goto err;
        }
@@ -310,39 +362,83 @@ static int __init gx1fb_init(void)
                ret = -EINVAL;
                goto err;
        }
+       pci_set_drvdata(pdev, info);
        printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
        return 0;
 
   err:
-       if (info->screen_base)
+       if (info->screen_base) {
                iounmap(info->screen_base);
-       if (par->vid_regs)
+               pci_release_region(pdev, 0);
+       }
+       if (par->vid_regs) {
                iounmap(par->vid_regs);
-       if (par->dc_regs)
+               pci_release_region(pdev, 1);
+       }
+       if (par->dc_regs) {
                iounmap(par->dc_regs);
-       if (par->vid_dev)
-               pci_dev_put(par->vid_dev);
+               release_mem_region(gx1_gx_base() + 0x8300, 0x100);
+       }
+
+       pci_disable_device(pdev);
+
        if (info)
                framebuffer_release(info);
        return ret;
 }
 
-static void __exit gx1fb_cleanup(void)
+static void gx1fb_remove(struct pci_dev *pdev)
 {
-       struct fb_info *info = gx1fb_info;
-       struct geodefb_par *par = gx1fb_info->par;
+       struct fb_info *info = pci_get_drvdata(pdev);
+       struct geodefb_par *par = info->par;
 
        unregister_framebuffer(info);
 
        iounmap((void __iomem *)info->screen_base);
+       pci_release_region(pdev, 0);
+
        iounmap(par->vid_regs);
+       pci_release_region(pdev, 1);
+
        iounmap(par->dc_regs);
+       release_mem_region(gx1_gx_base() + 0x8300, 0x100);
 
-       pci_dev_put(par->vid_dev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
 
        framebuffer_release(info);
 }
 
+static struct pci_device_id gx1fb_id_table[] = {
+       { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_VIDEO,
+         PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+         0xff0000, 0 },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, gx1fb_id_table);
+
+static struct pci_driver gx1fb_driver = {
+       .name           = "gx1fb",
+       .id_table       = gx1fb_id_table,
+       .probe          = gx1fb_probe,
+       .remove         = gx1fb_remove,
+};
+
+static int __init gx1fb_init(void)
+{
+#ifndef MODULE
+       if (fb_get_options("gx1fb", NULL))
+               return -ENODEV;
+#endif
+       return pci_register_driver(&gx1fb_driver);
+}
+
+static void __exit gx1fb_cleanup(void)
+{
+       pci_unregister_driver(&gx1fb_driver);
+}
+
 module_init(gx1fb_init);
 module_exit(gx1fb_cleanup);
 
index d3764acf8443f1cc5c0ac4841d9166bceac448c2..649c3943d4312df72b154cc5121451b07dc04b41 100644 (file)
@@ -69,8 +69,6 @@ static const struct cs5530_pll_entry cs5530_pll_table[] = {
        {  4310, 0x2FB1B802, }, /* 232.0000 */
 };
 
-#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
-
 static void cs5530_set_dclk_frequency(struct fb_info *info)
 {
        struct geodefb_par *par = info->par;
@@ -82,7 +80,7 @@ static void cs5530_set_dclk_frequency(struct fb_info *info)
        value = cs5530_pll_table[0].pll_value;
        min = cs5530_pll_table[0].pixclock - info->var.pixclock;
        if (min < 0) min = -min;
-       for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
+       for (i = 1; i < ARRAY_SIZE(cs5530_pll_table); i++) {
                diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
                if (diff < 0L) diff = -diff;
                if (diff < min) {
index 794ae76c7c4b982b363749085317bac2dbfc5329..96e08c8ded97911019c07c4917cfa430925dd85a 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-$(CONFIG_FB_I810)          += i810fb.o
 
-
 i810fb-objs                     := i810_main.o i810_accel.o
 
 ifdef CONFIG_FB_I810_GTF
@@ -12,3 +11,7 @@ i810fb-objs                     += i810_gtf.o
 else
 i810fb-objs                     += i810_dvt.o
 endif
+
+ifdef CONFIG_FB_I810_I2C
+i810fb-objs += i810-i2c.o
+endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
new file mode 100644 (file)
index 0000000..fda53aa
--- /dev/null
@@ -0,0 +1,257 @@
+ /*-*- linux-c -*-
+ *  linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support
+ *
+ *      Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+#include "i810.h"
+#include "i810_regs.h"
+#include "../edid.h"
+
+#define I810_DDC 0x50
+/* bit locations in the registers */
+#define SCL_DIR_MASK           0x0001
+#define SCL_DIR                        0x0002
+#define SCL_VAL_MASK           0x0004
+#define SCL_VAL_OUT            0x0008
+#define SCL_VAL_IN             0x0010
+#define SDA_DIR_MASK           0x0100
+#define SDA_DIR                        0x0200
+#define SDA_VAL_MASK           0x0400
+#define SDA_VAL_OUT            0x0800
+#define SDA_VAL_IN             0x1000
+
+#define DEBUG  /* define this for verbose EDID parsing output */
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(fmt,## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+static void i810i2c_setscl(void *data, int state)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                        *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+                   SCL_DIR_MASK | SCL_VAL_MASK);
+       i810_readl(mmio, GPIOB);        /* flush posted write */
+}
+
+static void i810i2c_setsda(void *data, int state)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                        *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+                   SDA_DIR_MASK | SDA_VAL_MASK);
+       i810_readl(mmio, GPIOB);        /* flush posted write */
+}
+
+static int i810i2c_getscl(void *data)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                        *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOB, SCL_DIR_MASK);
+       i810_writel(mmio, GPIOB, 0);
+       return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN));
+}
+
+static int i810i2c_getsda(void *data)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                        *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOB, SDA_DIR_MASK);
+       i810_writel(mmio, GPIOB, 0);
+       return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN));
+}
+
+static void i810ddc_setscl(void *data, int state)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par       *par = chan->par;
+       u8                      *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+                   SCL_DIR_MASK | SCL_VAL_MASK);
+       i810_readl(mmio, GPIOA);        /* flush posted write */
+}
+
+static void i810ddc_setsda(void *data, int state)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                      *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+                   SDA_DIR_MASK | SDA_VAL_MASK);
+       i810_readl(mmio, GPIOA);        /* flush posted write */
+}
+
+static int i810ddc_getscl(void *data)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                      *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOA, SCL_DIR_MASK);
+       i810_writel(mmio, GPIOA, 0);
+       return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN));
+}
+
+static int i810ddc_getsda(void *data)
+{
+        struct i810fb_i2c_chan    *chan = (struct i810fb_i2c_chan *)data;
+        struct i810fb_par         *par = chan->par;
+       u8                      *mmio = par->mmio_start_virtual;
+
+       i810_writel(mmio, GPIOA, SDA_DIR_MASK);
+       i810_writel(mmio, GPIOA, 0);
+       return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN));
+}
+
+#define I2C_ALGO_DDC_I810   0x0e0000
+#define I2C_ALGO_I2C_I810   0x0f0000
+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name,
+                             int conn)
+{
+        int rc;
+
+        strcpy(chan->adapter.name, name);
+        chan->adapter.owner             = THIS_MODULE;
+        chan->adapter.algo_data         = &chan->algo;
+        chan->adapter.dev.parent        = &chan->par->dev->dev;
+       switch (conn) {
+       case 1:
+               chan->adapter.id                = I2C_ALGO_DDC_I810;
+               chan->algo.setsda               = i810ddc_setsda;
+               chan->algo.setscl               = i810ddc_setscl;
+               chan->algo.getsda               = i810ddc_getsda;
+               chan->algo.getscl               = i810ddc_getscl;
+               break;
+       case 2:
+               chan->adapter.id                = I2C_ALGO_I2C_I810;
+               chan->algo.setsda               = i810i2c_setsda;
+               chan->algo.setscl               = i810i2c_setscl;
+               chan->algo.getsda               = i810i2c_getsda;
+               chan->algo.getscl               = i810i2c_getscl;
+               break;
+       }
+       chan->algo.udelay               = 10;
+       chan->algo.mdelay               = 10;
+        chan->algo.timeout              = (HZ/2);
+        chan->algo.data                 = chan;
+
+        i2c_set_adapdata(&chan->adapter, chan);
+
+        /* Raise SCL and SDA */
+        chan->algo.setsda(chan, 1);
+        chan->algo.setscl(chan, 1);
+        udelay(20);
+
+        rc = i2c_bit_add_bus(&chan->adapter);
+        if (rc == 0)
+                dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
+        else
+                dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
+                        "%s.\n", name);
+        return rc;
+}
+
+void i810_create_i2c_busses(struct i810fb_par *par)
+{
+        par->chan[0].par        = par;
+       par->chan[1].par        = par;
+       i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1);
+       i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2);
+}
+
+void i810_delete_i2c_busses(struct i810fb_par *par)
+{
+        if (par->chan[0].par)
+                i2c_bit_del_bus(&par->chan[0].adapter);
+        par->chan[0].par = NULL;
+       if (par->chan[1].par)
+               i2c_bit_del_bus(&par->chan[1].adapter);
+       par->chan[1].par = NULL;
+}
+
+static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan)
+{
+        u8 start = 0x0;
+        struct i2c_msg msgs[] = {
+                {
+                        .addr   = I810_DDC,
+                        .len    = 1,
+                        .buf    = &start,
+                }, {
+                        .addr   = I810_DDC,
+                        .flags  = I2C_M_RD,
+                        .len    = EDID_LENGTH,
+                },
+        };
+        u8 *buf;
+
+        buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+        if (!buf) {
+               DPRINTK("i810-i2c: Failed to allocate memory\n");
+                return NULL;
+        }
+        msgs[1].buf = buf;
+
+        if (i2c_transfer(&chan->adapter, msgs, 2) == 2) {
+               DPRINTK("i810-i2c: I2C Transfer successful\n");
+                return buf;
+       }
+        DPRINTK("i810-i2c: Unable to read EDID block.\n");
+        kfree(buf);
+        return NULL;
+}
+
+int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
+{
+       struct i810fb_par *par = info->par;
+        u8 *edid = NULL;
+        int i;
+
+       DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn);
+       if (conn < 3) {
+               for (i = 0; i < 3; i++) {
+                       /* Do the real work */
+                       edid = i810_do_probe_i2c_edid(&par->chan[conn-1]);
+                       if (edid)
+                               break;
+               }
+       } else {
+               DPRINTK("i810-i2c: Getting EDID from BIOS\n");
+               edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+               if (edid)
+                       memcpy(edid, fb_firmware_edid(info->device),
+                              EDID_LENGTH);
+       }
+
+        if (out_edid)
+                *out_edid = edid;
+
+        return (edid) ? 0 : 1;
+}
+
+
index fe3b757947563ec23b8e347bb958c6ca4a0e8262..d48949ceaacc033988512bb6eb4dabf3e942a0e3 100644 (file)
@@ -16,6 +16,9 @@
 #include <linux/list.h>
 #include <linux/agp_backend.h>
 #include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
 #include <video/vga.h>
 
 /* Fence */
 #define HAS_ACCELERATION            2
 #define ALWAYS_SYNC                 4
 #define LOCKUP                      8
-#define USE_HWCUR                  16
 
 struct gtt_data {
        struct agp_memory *i810_fb_memory;
@@ -241,6 +243,14 @@ struct state_registers {
        u8 cr39, cr41, cr70, sr01, msr;
 };
 
+struct i810fb_par;
+
+struct i810fb_i2c_chan {
+       struct i810fb_par *par;
+       struct i2c_adapter adapter;
+       struct i2c_algo_bit_data algo;
+};
+
 struct i810fb_par {
        struct mode_registers    regs;
        struct state_registers   hw_state;
@@ -252,10 +262,12 @@ struct i810fb_par {
        struct heap_data         iring;
        struct heap_data         cursor_heap;
        struct vgastate          state;
+       struct i810fb_i2c_chan   chan[2];
        atomic_t                 use_count;
        u32 pseudo_palette[17];
        unsigned long mmio_start_phys;
        u8 __iomem *mmio_start_virtual;
+       u8 *edid;
        u32 pitch;
        u32 pixconf;
        u32 watermark;
index 6db183462b9200ff642b364492bb39c971ad1d4d..0dbc9ddb6766e78eba0b1b58f5e5eb0c57d0051b 100644 (file)
@@ -92,20 +92,21 @@ static struct pci_driver i810fb_driver = {
        .resume   =     i810fb_resume,
 };
 
-static int vram       __initdata = 4;
-static int bpp        __initdata = 8;
-static int mtrr       __initdata = 0;
-static int accel      __initdata = 0;
-static int hsync1     __initdata = 0;
-static int hsync2     __initdata = 0;
-static int vsync1     __initdata = 0;
-static int vsync2     __initdata = 0;
-static int xres       __initdata = 640;
-static int yres       __initdata = 480;
-static int vyres      __initdata = 0;
-static int sync       __initdata = 0;
-static int ext_vga    __initdata = 0;
-static int dcolor     __initdata = 0;
+static char *mode_option __devinitdata = NULL;
+static int vram       __devinitdata = 4;
+static int bpp        __devinitdata = 8;
+static int mtrr       __devinitdata;
+static int accel      __devinitdata;
+static int hsync1     __devinitdata;
+static int hsync2     __devinitdata;
+static int vsync1     __devinitdata;
+static int vsync2     __devinitdata;
+static int xres       __devinitdata;
+static int yres       __devinitdata;
+static int vyres      __devinitdata;
+static int sync       __devinitdata;
+static int extvga     __devinitdata;
+static int dcolor     __devinitdata;
 
 /*------------------------------------------------------------*/
 
@@ -310,6 +311,8 @@ static void i810_hires(u8 __iomem *mmio)
        val = i810_readb(CR_DATA_CGA, mmio);
        i810_writeb(CR_INDEX_CGA, mmio, CR80);
        i810_writeb(CR_DATA_CGA, mmio, val | 1);
+       /* Stop LCD displays from flickering */
+       i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);
 }
 
 /**
@@ -947,31 +950,24 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                             struct fb_info *info)
 {
        struct i810fb_par *par = (struct i810fb_par *) info->par;
-       int line_length, vidmem;
-       u32 xres, yres, vxres, vyres;
-
-       xres = var->xres;
-       yres = var->yres;
-       vxres = var->xres_virtual;
-       vyres = var->yres_virtual;
-
+       int line_length, vidmem, mode_valid = 0, retval = 0;
+       u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
        /*
         *  Memory limit
         */
-       line_length = get_line_length(par, vxres, 
-                                     var->bits_per_pixel);
-
+       line_length = get_line_length(par, vxres, var->bits_per_pixel);
        vidmem = line_length*vyres;
+
        if (vidmem > par->fb.size) {
                vyres = par->fb.size/line_length;
-               if (vyres < yres) {
+               if (vyres < var->yres) {
                        vyres = yres;
                        vxres = par->fb.size/vyres;
                        vxres /= var->bits_per_pixel >> 3;
                        line_length = get_line_length(par, vxres, 
                                                      var->bits_per_pixel);
                        vidmem = line_length * yres;
-                       if (vxres < xres) {
+                       if (vxres < var->xres) {
                                printk("i810fb: required video memory, "
                                       "%d bytes, for %dx%d-%d (virtual) "
                                       "is out of range\n", 
@@ -981,6 +977,10 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                        }
                }
        }
+
+       var->xres_virtual = vxres;
+       var->yres_virtual = vyres;
+
        /*
         * Monitor limit
         */
@@ -996,26 +996,41 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                info->monspecs.dclkmax = 204000000;
                break;
        }
+
        info->monspecs.dclkmin = 15000000;
 
-       if (fb_validate_mode(var, info)) {
+       if (!fb_validate_mode(var, info))
+               mode_valid = 1;
+
+#ifdef CONFIG_FB_I810_I2C
+       if (!mode_valid && info->monspecs.gtf &&
+           !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+               mode_valid = 1;
+
+       if (!mode_valid && info->monspecs.modedb_len) {
+               struct fb_videomode *mode;
+
+               mode = fb_find_best_mode(var, &info->modelist);
+               if (mode) {
+                       fb_videomode_to_var(var, mode);
+                       mode_valid = 1;
+               }
+       }
+#endif
+       if (!mode_valid && info->monspecs.modedb_len == 0) {
                if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) {
                        int default_sync = (info->monspecs.hfmin-HFMIN)
-                                               |(info->monspecs.hfmax-HFMAX)
-                                               |(info->monspecs.vfmin-VFMIN)
-                                               |(info->monspecs.vfmax-VFMAX);
+                               |(info->monspecs.hfmax-HFMAX)
+                               |(info->monspecs.vfmin-VFMIN)
+                               |(info->monspecs.vfmax-VFMAX);
                        printk("i810fb: invalid video mode%s\n",
-                           default_sync ? "" :
-                           ". Specifying vsyncN/hsyncN parameters may help");
-                       return -EINVAL;
+                              default_sync ? "" : ". Specifying "
+                              "vsyncN/hsyncN parameters may help");
+                       retval = -EINVAL;
                }
        }
-       
-       var->xres = xres;
-       var->yres = yres;
-       var->xres_virtual = vxres;
-       var->yres_virtual = vyres;
-       return 0;
+
+       return retval;
 }      
 
 /**
@@ -1375,7 +1390,6 @@ static int i810fb_set_par(struct fb_info *info)
        decode_var(&info->var, par);
        i810_load_regs(par);
        i810_init_cursor(par);
-
        encode_fix(&info->fix, info);
 
        if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
@@ -1418,9 +1432,8 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        struct i810fb_par *par = (struct i810fb_par *)info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
 
-       if (!(par->dev_flags & USE_HWCUR) || !info->var.accel_flags ||
-           par->dev_flags & LOCKUP)
-               return soft_cursor(info, cursor);
+       if (!par->dev_flags & LOCKUP)
+               return -ENXIO;
 
        if (cursor->image.width > 64 || cursor->image.height > 64)
                return -ENXIO;
@@ -1712,12 +1725,21 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
        if (bpp < 8)
                bpp = 8;
        
+       par->i810fb_ops = i810fb_ops;
+
+       if (xres)
+               info->var.xres = xres;
+       else
+               info->var.xres = 640;
+
+       if (yres)
+               info->var.yres = yres;
+       else
+               info->var.yres = 480;
+
        if (!vyres) 
-               vyres = (vram << 20)/(xres*bpp >> 3);
+               vyres = (vram << 20)/(info->var.xres*bpp >> 3);
 
-       par->i810fb_ops = i810fb_ops;
-       info->var.xres = xres;
-       info->var.yres = yres;
        info->var.yres_virtual = vyres;
        info->var.bits_per_pixel = bpp;
 
@@ -1744,7 +1766,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
        i810_init_cursor(par);
 
        /* mvo: enable external vga-connector (for laptops) */
-       if (ext_vga) {
+       if (extvga) {
                i810_writel(HVSYNC, mmio, 0);
                i810_writel(PWR_CLKC, mmio, 3);
        }
@@ -1814,8 +1836,80 @@ i810_allocate_pci_resource(struct i810fb_par *par,
        return 0;
 }
 
+static void __devinit i810fb_find_init_mode(struct fb_info *info)
+{
+       struct fb_videomode mode;
+       struct fb_var_screeninfo var;
+       struct fb_monspecs *specs = &info->monspecs;
+       int found = 0;
+#ifdef CONFIG_FB_I810_I2C
+       int i;
+       int err;
+       struct i810fb_par *par = info->par;
+#endif
+
+       INIT_LIST_HEAD(&info->modelist);
+       memset(&mode, 0, sizeof(struct fb_videomode));
+       var = info->var;
+#ifdef CONFIG_FB_I810_I2C
+       i810_create_i2c_busses(par);
+
+       for (i = 0; i < 3; i++) {
+               err = i810_probe_i2c_connector(info, &par->edid, i+1);
+               if (!err)
+                       break;
+       }
+
+       if (!err)
+               printk("i810fb_init_pci: DDC probe successful\n");
+
+       fb_edid_to_monspecs(par->edid, specs);
+
+       if (specs->modedb == NULL)
+               printk("i810fb_init_pci: Unable to get Mode Database\n");
+
+       fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
+                                &info->modelist);
+       if (specs->modedb != NULL) {
+               if (xres && yres) {
+                       struct fb_videomode *m;
+
+                       if ((m = fb_find_best_mode(&var, &info->modelist))) {
+                               mode = *m;
+                               found  = 1;
+                       }
+               }
+
+               if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
+                       for (i = 0; i < specs->modedb_len; i++) {
+                               if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+                                       mode = specs->modedb[i];
+                                       found = 1;
+                                       break;
+                               }
+                       }
+               }
+
+               if (!found) {
+                       mode = specs->modedb[0];
+                       found = 1;
+               }
+
+               fb_videomode_to_var(&var, &mode);
+       }
+#endif
+       if (mode_option)
+               fb_find_mode(&var, info, mode_option, specs->modedb,
+                            specs->modedb_len, (found) ? &mode : NULL,
+                            info->var.bits_per_pixel);
+
+       info->var = var;
+       fb_destroy_modedb(specs->modedb);
+       specs->modedb = NULL;
+}
+
 #ifndef MODULE
-static int __init i810fb_setup(char *options)
+static int __devinit i810fb_setup(char *options)
 {
        char *this_opt, *suffix = NULL;
 
@@ -1827,8 +1921,8 @@ static int __init i810fb_setup(char *options)
                        mtrr = 1;
                else if (!strncmp(this_opt, "accel", 5))
                        accel = 1;
-               else if (!strncmp(this_opt, "ext_vga", 7))
-                       ext_vga = 1;
+               else if (!strncmp(this_opt, "extvga", 6))
+                       extvga = 1;
                else if (!strncmp(this_opt, "sync", 4))
                        sync = 1;
                else if (!strncmp(this_opt, "vram:", 5))
@@ -1857,6 +1951,8 @@ static int __init i810fb_setup(char *options)
                        vsync2 = simple_strtoul(this_opt+7, NULL, 0);
                else if (!strncmp(this_opt, "dcolor", 6))
                        dcolor = 1;
+               else
+                       mode_option = this_opt;
        }
        return 0;
 }
@@ -1867,6 +1963,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
 {
        struct fb_info    *info;
        struct i810fb_par *par = NULL;
+       struct fb_videomode mode;
        int i, err = -1, vfreq, hfreq, pixclock;
 
        i = 0;
@@ -1875,7 +1972,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
        if (!info)
                return -ENOMEM;
 
-       par = (struct i810fb_par *) info->par;
+       par = info->par;
        par->dev = dev;
 
        if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
@@ -1906,15 +2003,20 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
        info->fbops = &par->i810fb_ops;
        info->pseudo_palette = par->pseudo_palette;
        fb_alloc_cmap(&info->cmap, 256, 0);
+       i810fb_find_init_mode(info);
 
        if ((err = info->fbops->fb_check_var(&info->var, info))) {
                i810fb_release_resource(info, par);
                return err;
        }
+
+       fb_var_to_videomode(&mode, &info->var);
+       fb_add_videomode(&mode, &info->modelist);
        encode_fix(&info->fix, info); 
                    
        i810fb_init_ringbuffer(info);
        err = register_framebuffer(info);
+
        if (err < 0) {
                i810fb_release_resource(info, par); 
                printk("i810fb_init: cannot register framebuffer device\n");
@@ -1953,6 +2055,8 @@ static void i810fb_release_resource(struct fb_info *info,
        struct gtt_data *gtt = &par->i810_gtt;
        unset_mtrr(par);
 
+       i810_delete_i2c_busses(par);
+
        if (par->i810_gtt.i810_cursor_memory)
                agp_free_memory(gtt->i810_cursor_memory);
        if (par->i810_gtt.i810_fb_memory)
@@ -1962,7 +2066,8 @@ static void i810fb_release_resource(struct fb_info *info,
                iounmap(par->mmio_start_virtual);
        if (par->aperture.virtual)
                iounmap(par->aperture.virtual);
-
+       if (par->edid)
+               kfree(par->edid);
        if (par->res_flags & FRAMEBUFFER_REQ)
                release_mem_region(par->aperture.physical,
                                   par->aperture.size);
@@ -1988,7 +2093,7 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
 }                                                      
 
 #ifndef MODULE
-static int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
 {
        char *option = NULL;
 
@@ -2006,7 +2111,7 @@ static int __init i810fb_init(void)
 
 #ifdef MODULE
 
-static int __init i810fb_init(void)
+static int __devinit i810fb_init(void)
 {
        hsync1 *= 1000;
        hsync2 *= 1000;
@@ -2046,14 +2151,16 @@ module_param(accel, bool, 0);
 MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
 module_param(mtrr, bool, 0);
 MODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)");
-module_param(ext_vga, bool, 0);
-MODULE_PARM_DESC(ext_vga, "Enable external VGA connector (default = 0)");
+module_param(extvga, bool, 0);
+MODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)");
 module_param(sync, bool, 0);
 MODULE_PARM_DESC(sync, "wait for accel engine to finish drawing"
                 " (default = 0)");
 module_param(dcolor, bool, 0);
 MODULE_PARM_DESC(dcolor, "use DirectColor visuals"
                 " (default = 0 = TrueColor)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
 
 MODULE_AUTHOR("Tony A. Daplas");
 MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
index 43b4297b4d481642b1c38aa5731f542076a8361c..06072a6466f2cee0fc46be91e9e11b9fc716bea3 100644 (file)
@@ -83,6 +83,22 @@ extern int  i810fb_sync     (struct fb_info *p);
 extern void i810fb_init_ringbuffer(struct fb_info *info);
 extern void i810fb_load_front     (u32 offset, struct fb_info *info);
 
+#ifdef CONFIG_FB_I810_I2C
+/* I2C */
+extern int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+                                   int conn);
+extern void i810_create_i2c_busses(struct i810fb_par *par);
+extern void i810_delete_i2c_busses(struct i810fb_par *par);
+#else
+static inline int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid,
+                                   int conn)
+{
+       return 1;
+}
+static inline void i810_create_i2c_busses(struct i810fb_par *par) { }
+static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
+#endif
+
 /* Conditionals */
 #ifdef CONFIG_X86
 inline void flush_cache(void)
index 6680ec9ba69eac232cd4cb950f88aa57171b7a47..011e11626558399a98890554878a3c4f6af4fa6c 100644 (file)
@@ -234,7 +234,6 @@ struct intelfb_info {
 
        /* palette */
        u32 pseudo_palette[17];
-       struct { u8 red, green, blue, pad; } palette[256];
 
        /* chip info */
        int pci_chipset;
index a112a1786855feb07b581fb184517e5622ff6762..bf62e6ed0382c9a0cabe0ba632288ff85d26f44a 100644 (file)
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
 #include <linux/pagemap.h>
 #include <linux/version.h>
 
@@ -242,7 +238,7 @@ static int voffset  = 48;
 static char *mode       = NULL;
 
 module_param(accel, bool, S_IRUGO);
-MODULE_PARM_DESC(accel, "Enable console acceleration");
+MODULE_PARM_DESC(accel, "Enable hardware acceleration");
 module_param(vram, int, S_IRUGO);
 MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
 module_param(voffset, int, S_IRUGO);
@@ -498,7 +494,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct fb_info *info;
        struct intelfb_info *dinfo;
-       int i, j, err, dvo;
+       int i, err, dvo;
        int aperture_size, stolen_size;
        struct agp_kern_info gtt_info;
        int agp_memtype;
@@ -845,13 +841,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (bailearly == 5)
                bailout(dinfo);
 
-       for (i = 0; i < 16; i++) {
-               j = color_table[i];
-               dinfo->palette[i].red = default_red[j];
-               dinfo->palette[i].green = default_grn[j];
-               dinfo->palette[i].blue = default_blu[j];
-       }
-
        if (bailearly == 6)
                bailout(dinfo);
 
@@ -1363,10 +1352,6 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                        green >>= 8;
                        blue >>= 8;
 
-                       dinfo->palette[regno].red = red;
-                       dinfo->palette[regno].green = green;
-                       dinfo->palette[regno].blue = blue;
-
                        intelfbhw_setcolreg(dinfo, regno, red, green, blue,
                                            transp);
                }
@@ -1499,7 +1484,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 #endif
 
        if (!dinfo->hwcursor)
-               return soft_cursor(info, cursor);
+               return -ENXIO;
 
        intelfbhw_cursor_hide(dinfo);
 
index f5bed581dc45f3e3dd6406a8246a9647f5574ba6..5bafc3c54db767a41730105f18df9f104d8ad694 100644 (file)
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
-#include <linux/kd.h>
-#include <linux/vt_kern.h>
 #include <linux/pagemap.h>
 #include <linux/version.h>
 
index a18dd024fc86a9384b67c49391c1685ca75e95f3..d9d3e9f6c08e245d54c8cf0621b340e03708fcc3 100644 (file)
@@ -68,6 +68,9 @@
  *               "David C. Hansen" <haveblue@us.ibm.com>
  *                     Fixes
  *
+ *               "Ian Romanick" <idr@us.ibm.com>
+ *                     Find PInS data in BIOS on PowerPC systems.
+ *
  * (following author is not in any relation with this code, but his code
  *  is included in this driver)
  *
@@ -496,10 +499,35 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
        get_bios_version(vbios, bd);
        get_bios_output(vbios, bd);
        get_bios_tvout(vbios, bd);
+#if defined(__powerpc__)
+       /* On PowerPC cards, the PInS offset isn't stored at the end of the
+        * BIOS image.  Instead, you must search the entire BIOS image for
+        * the magic PInS signature.
+        *
+        * This actually applies to all OpenFirmware base cards.  Since these
+        * cards could be put in a MIPS or SPARC system, should the condition
+        * be something different?
+        */
+       for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
+               unsigned char header[3];
+
+               header[0] = readb(vbios + pins_offset);
+               header[1] = readb(vbios + pins_offset + 1);
+               header[2] = readb(vbios + pins_offset + 2);
+               if ( (header[0] == 0x2E) && (header[1] == 0x41)
+                    && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
+                       printk(KERN_INFO "PInS data found at offset %u\n",
+                              pins_offset);
+                       get_pins(vbios + pins_offset, bd);
+                       break;
+               }
+       }
+#else
        pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
        if (pins_offset <= 0xFF80) {
                get_pins(vbios + pins_offset, bd);
        }
+#endif
 }
 
 #define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
@@ -755,6 +783,8 @@ void matroxfb_read_pins(WPMINFO2) {
        }
 #endif
        matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios));
+       printk(KERN_INFO "PInS memtype = %u\n",
+              (ACCESS_FBINFO(values).reg.opt & 0x1C00) >> 10);
 }
 
 EXPORT_SYMBOL(matroxfb_DAC_in);
index 3edc9f49344b6df9038988e08377b19f4839a149..47516c44a390ac7218a3df538424553f76ac9225 100644 (file)
@@ -456,12 +456,22 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
  *
  *     Valid mode specifiers for @mode_option:
  *
- *     <xres>x<yres>[-<bpp>][@<refresh>] or
+ *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
  *     <name>[-<bpp>][@<refresh>]
  *
  *     with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
  *     <name> a string.
  *
+ *      If 'M' is present after yres (and before refresh/bpp if present),
+ *      the function will compute the timings using VESA(tm) Coordinated
+ *      Video Timings (CVT).  If 'R' is present after 'M', will compute with
+ *      reduced blanking (for flatpanels).  If 'i' is present, compute
+ *      interlaced mode.  If 'm' is present, add margins equal to 1.8%
+ *      of xres rounded down to 8 pixels, and 1.8% of yres. The char
+ *      'i' and 'm' must be after 'M' and 'R'. Example:
+ *
+ *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
+ *
  *     NOTE: The passed struct @var is _not_ cleared!  This allows you
  *     to supply values for e.g. the grayscale and accel_flags fields.
  *
@@ -495,7 +505,7 @@ int fb_find_mode(struct fb_var_screeninfo *var,
        unsigned int namelen = strlen(name);
        int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
        unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
-       int yres_specified = 0;
+       int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
        u32 best, diff;
 
        for (i = namelen-1; i >= 0; i--) {
@@ -506,6 +516,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                        !yres_specified) {
                        refresh = my_atoi(&name[i+1]);
                        refresh_specified = 1;
+                       if (cvt || rb)
+                           cvt = 0;
                    } else
                        goto done;
                    break;
@@ -514,6 +526,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                    if (!bpp_specified && !yres_specified) {
                        bpp = my_atoi(&name[i+1]);
                        bpp_specified = 1;
+                       if (cvt || rb)
+                           cvt = 0;
                    } else
                        goto done;
                    break;
@@ -526,6 +540,22 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                    break;
                case '0'...'9':
                    break;
+               case 'M':
+                   if (!yres_specified)
+                       cvt = 1;
+                   break;
+               case 'R':
+                   if (!cvt)
+                       rb = 1;
+                   break;
+               case 'm':
+                   if (!cvt)
+                       margins = 1;
+                   break;
+               case 'i':
+                   if (!cvt)
+                       interlace = 1;
+                   break;
                default:
                    goto done;
            }
@@ -535,6 +565,34 @@ int fb_find_mode(struct fb_var_screeninfo *var,
            res_specified = 1;
        }
 done:
+       if (cvt) {
+           struct fb_videomode cvt_mode;
+           int ret;
+
+           DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres,
+                   (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
+                   "", (margins) ? " with margins" : "", (interlace) ?
+                   " interlaced" : "");
+
+           cvt_mode.xres = xres;
+           cvt_mode.yres = yres;
+           cvt_mode.refresh = (refresh) ? refresh : 60;
+
+           if (interlace)
+               cvt_mode.vmode |= FB_VMODE_INTERLACED;
+           else
+               cvt_mode.vmode &= ~FB_VMODE_INTERLACED;
+
+           ret = fb_find_mode_cvt(&cvt_mode, margins, rb);
+
+           if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) {
+               DPRINTK("modedb CVT: CVT mode ok\n");
+               return 1;
+           }
+
+           DPRINTK("CVT mode invalid, getting mode from database\n");
+       }
+
        DPRINTK("Trying specified video mode%s %ix%i\n",
            refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
 
index 1a91bffdda26b78b6cbc38256c856b6f1b0264a9..ace484fa61ce09fb00512d54d5e7eee2bcfc6a3d 100644 (file)
@@ -194,8 +194,9 @@ static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
        return NULL;
 }
 
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
 {
+       struct nvidia_par *par = info->par;
        u8 *edid = NULL;
        int i;
 
@@ -205,10 +206,17 @@ int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
                if (edid)
                        break;
        }
+
+       if (!edid && conn == 1) {
+               /* try to get from firmware */
+               edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+               if (edid)
+                       memcpy(edid, fb_firmware_edid(info->device),
+                              EDID_LENGTH);
+       }
+
        if (out_edid)
                *out_edid = edid;
-       if (!edid)
-               return 1;
 
-       return 0;
+       return (edid) ? 0 : 1;
 }
index 9da320986f4c924900e7ff1358232428e88c7c42..afee284fc73c964bbc4fb2782c0fa251b13ccb28 100644 (file)
@@ -95,6 +95,7 @@
 
 #define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
 
+#ifdef __LITTLE_ENDIAN
 #define reverse_order(l)        \
 do {                            \
        u8 *a = (u8 *)(l);      \
@@ -103,5 +104,8 @@ do {                            \
        *a = byte_rev[*a], a++; \
        *a = byte_rev[*a];      \
 } while(0)
+#else
+#define reverse_order(l)
+#endif                          /* __LITTLE_ENDIAN */
 
 #endif                         /* __NV_LOCAL_H__ */
index 7d12eb85310de04c9043d4408dda2d005a92c4da..4fa2cf9a8af2adbf6e673022ea2655c9810e5de6 100644 (file)
@@ -30,8 +30,9 @@
 void nvidia_create_i2c_busses(struct nvidia_par *par) {}
 void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
 
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
 {
+       struct nvidia_par *par = info->par;
        struct device_node *dp;
        unsigned char *pedid = NULL;
        unsigned char *disptype = NULL;
index 42847ce1b8dd7690c131a4ffe2f425499fb2f25c..cac44fc7f58717be955c65c1e43c2156a6343372 100644 (file)
@@ -34,7 +34,7 @@ void NVLockUnlock(struct nvidia_par *par, int);
 #if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
 void nvidia_create_i2c_busses(struct nvidia_par *par);
 void nvidia_delete_i2c_busses(struct nvidia_par *par);
-int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
+int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
                               u8 ** out_edid);
 #else
 #define nvidia_create_i2c_busses(...)
index 0bbdca2e0f911862686e5559568d70e0e8af3c65..11c84178f42069c83163ea01512c39707897d249 100644 (file)
@@ -401,7 +401,7 @@ void NVCommonSetup(struct fb_info *info)
        nvidia_create_i2c_busses(par);
        if (!par->twoHeads) {
                par->CRTCnumber = 0;
-               nvidia_probe_i2c_connector(par, 1, &edidA);
+               nvidia_probe_i2c_connector(info, 1, &edidA);
                if (edidA && !fb_parse_edid(edidA, &var)) {
                        printk("nvidiafb: EDID found from BUS1\n");
                        monA = &monitorA;
@@ -488,14 +488,14 @@ void NVCommonSetup(struct fb_info *info)
                oldhead = NV_RD32(par->PCRTC0, 0x00000860);
                NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
 
-               nvidia_probe_i2c_connector(par, 1, &edidA);
+               nvidia_probe_i2c_connector(info, 1, &edidA);
                if (edidA && !fb_parse_edid(edidA, &var)) {
                        printk("nvidiafb: EDID found from BUS1\n");
                        monA = &monitorA;
                        fb_edid_to_monspecs(edidA, monA);
                }
 
-               nvidia_probe_i2c_connector(par, 2, &edidB);
+               nvidia_probe_i2c_connector(info, 2, &edidB);
                if (edidB && !fb_parse_edid(edidB, &var)) {
                        printk("nvidiafb: EDID found from BUS2\n");
                        monB = &monitorB;
index 30f80c23f934bb0a76719232f492153fc7cca00a..3620de0f252e6100c3da6a895de1cf7f3297dc14 100644 (file)
@@ -658,7 +658,7 @@ static int nvidia_calc_regs(struct fb_info *info)
 {
        struct nvidia_par *par = info->par;
        struct _riva_hw_state *state = &par->ModeReg;
-       int i, depth = fb_get_color_depth(&info->var);
+       int i, depth = fb_get_color_depth(&info->var, &info->fix);
        int h_display = info->var.xres / 8 - 1;
        int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
        int h_end = (info->var.xres + info->var.right_margin +
@@ -893,7 +893,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
        int i, set = cursor->set;
        u16 fg, bg;
 
-       if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+       if (!hwcur || cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
                return -ENXIO;
 
        NVShowHideCursor(par, 0);
@@ -978,6 +978,9 @@ static int nvidiafb_set_par(struct fb_info *info)
            !par->twoHeads)
                par->FPDither = 0;
 
+       info->fix.visual = (info->var.bits_per_pixel == 8) ?
+           FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
        nvidia_init_vga(info);
        nvidia_calc_regs(info);
        nvidia_write_regs(par);
@@ -992,9 +995,6 @@ static int nvidiafb_set_par(struct fb_info *info)
        NVWriteCrtc(par, 0x11, 0x00);
        info->fix.line_length = (info->var.xres_virtual *
                                 info->var.bits_per_pixel) >> 3;
-       info->fix.visual = (info->var.bits_per_pixel == 8) ?
-           FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-
        if (info->var.accel_flags) {
                info->fbops->fb_imageblit = nvidiafb_imageblit;
                info->fbops->fb_fillrect = nvidiafb_fillrect;
@@ -1328,7 +1328,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
                char buf[16];
 
                memset(buf, 0, 16);
-               snprintf(buf, 15, "%dx%d", par->fpWidth, par->fpHeight);
+               snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
                fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
                             specs->modedb_len, &modedb, 8);
        }
@@ -1356,8 +1356,6 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
        info->pixmap.size = 8 * 1024;
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
-       if (!hwcur)
-               info->fbops->fb_cursor = soft_cursor;
        info->var.accel_flags = (!noaccel);
 
        switch (par->Architecture) {
index 30112816420c71e2d304a538c82bd2129a0ecdf3..34d4dcc0320ac9774e2c480e0d9c43e140ead5fe 100644 (file)
@@ -467,6 +467,36 @@ static inline unsigned int get_pcd(unsigned int pixclock)
        return (unsigned int)pcd;
 }
 
+/*
+ * Some touchscreens need hsync information from the video driver to
+ * function correctly. We export it here.
+ */
+static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
+{
+       unsigned long long htime;
+
+       if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
+               fbi->hsync_time=0;
+               return;
+       }
+
+       htime = (unsigned long long)get_lcdclk_frequency_10khz() * 10000;
+       do_div(htime, pcd * fbi->fb.var.hsync_len);
+       fbi->hsync_time = htime;
+}
+
+unsigned long pxafb_get_hsync_time(struct device *dev)
+{
+       struct pxafb_info *fbi = dev_get_drvdata(dev);
+
+       /* If display is blanked/suspended, hsync isn't active */
+       if (!fbi || (fbi->state != C_ENABLE))
+               return 0;
+
+       return fbi->hsync_time;
+}
+EXPORT_SYMBOL(pxafb_get_hsync_time);
+
 /*
  * pxafb_activate_var():
  *     Configures LCD Controller based on entries in var parameter.  Settings are
@@ -631,6 +661,7 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
        fbi->reg_lccr1 = new_regs.lccr1;
        fbi->reg_lccr2 = new_regs.lccr2;
        fbi->reg_lccr3 = new_regs.lccr3;
+       set_hsync_time(fbi, pcd);
        local_irq_restore(flags);
 
        /*
@@ -907,6 +938,7 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
 
        case CPUFREQ_POSTCHANGE:
                pcd = get_pcd(fbi->fb.var.pixclock);
+               set_hsync_time(fbi, pcd);
                fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
                set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
                break;
index de15fec5f82f5717cf28c3d747064cadaf0cefda..22c00be786a8e28e12327051ae6473bb81eb4c47 100644 (file)
@@ -83,6 +83,8 @@ struct pxafb_info {
        u_int                   reg_lccr2;
        u_int                   reg_lccr3;
 
+       unsigned long   hsync_time;
+
        volatile u_char         state;
        volatile u_char         task_state;
        struct semaphore        ctrlr_sem;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
new file mode 100644 (file)
index 0000000..00c0223
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * linux/drivers/video/s3c2410fb.c
+ *     Copyright (c) Arnaud Patard, Ben Dooks
+ *
+ * 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.
+ *
+ *         S3C2410 LCD Controller Frame Buffer Driver
+ *         based on skeletonfb.c, sa1100fb.c and others
+ *
+ * ChangeLog
+ * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *      - u32 state -> pm_message_t state
+ *      - S3C2410_{VA,SZ}_LCD -> S3C24XX
+ *
+ * 2005-03-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *      - Removed the ioctl
+ *      - use readl/writel instead of __raw_writel/__raw_readl
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *      - Added the possibility to set on or off the
+ *      debugging mesaages
+ *      - Replaced 0 and 1 by on or off when reading the
+ *      /sys files
+ *
+ * 2005-03-23: Ben Dooks <ben-linux@fluff.org>
+ *     - added non 16bpp modes
+ *     - updated platform information for range of x/y/bpp
+ *     - add code to ensure palette is written correctly
+ *     - add pixel clock divisor control
+ *
+ * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - Removed the use of currcon as it no more exist
+ *     - Added LCD power sysfs interface
+ *
+ * 2004-11-03: Ben Dooks <ben-linux@fluff.org>
+ *     - minor cleanups
+ *     - add suspend/resume support
+ *     - s3c2410fb_setcolreg() not valid in >8bpp modes
+ *     - removed last CONFIG_FB_S3C2410_FIXED
+ *     - ensure lcd controller stopped before cleanup
+ *     - added sysfs interface for backlight power
+ *     - added mask for gpio configuration
+ *     - ensured IRQs disabled during GPIO configuration
+ *     - disable TPAL before enabling video
+ *
+ * 2004-09-20: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *      - Suppress command line options
+ *
+ * 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - code cleanup
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - Renamed from h1940fb.c to s3c2410fb.c
+ *     - Add support for different devices
+ *     - Backlight support
+ *
+ * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
+ *     - added clock (de-)allocation code
+ *     - added fixem fbmem option
+ *
+ * 2004-07-27: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - code cleanup
+ *     - added a forgotten return in h1940fb_init
+ *
+ * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at>
+ *     - code cleanup and extended debugging
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - First version
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#include <asm/mach/map.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/fb.h>
+#include <asm/hardware/clock.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#include "s3c2410fb.h"
+
+
+static struct s3c2410fb_mach_info *mach_info;
+
+/* Debugging stuff */
+#ifdef CONFIG_FB_S3C2410_DEBUG
+static int debug          = 1;
+#else
+static int debug          = 0;
+#endif
+
+#define dprintk(msg...)        if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
+
+/* useful functions */
+
+/* s3c2410fb_set_lcdaddr
+ *
+ * initialise lcd controller address pointers
+*/
+
+static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi)
+{
+       struct fb_var_screeninfo *var = &fbi->fb->var;
+       unsigned long saddr1, saddr2, saddr3;
+
+       saddr1  = fbi->fb->fix.smem_start >> 1;
+       saddr2  = fbi->fb->fix.smem_start;
+       saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8;
+       saddr2>>= 1;
+
+       saddr3 =  S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres);
+
+       dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
+       dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
+       dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
+
+       writel(saddr1, S3C2410_LCDSADDR1);
+       writel(saddr2, S3C2410_LCDSADDR2);
+       writel(saddr3, S3C2410_LCDSADDR3);
+}
+
+/* s3c2410fb_calc_pixclk()
+ *
+ * calculate divisor for clk->pixclk
+*/
+
+static unsigned int s3c2410fb_calc_pixclk(struct s3c2410fb_info *fbi,
+                                         unsigned long pixclk)
+{
+       unsigned long clk = clk_get_rate(fbi->clk);
+       unsigned long long div;
+
+       /* pixclk is in picoseoncds, our clock is in Hz
+        *
+        * Hz -> picoseconds is / 10^-12
+        */
+
+       div = (unsigned long long)clk * pixclk;
+       do_div(div,1000000UL);
+       do_div(div,1000000UL);
+
+       dprintk("pixclk %ld, divisor is %ld\n", pixclk, (long)div);
+       return div;
+}
+
+/*
+ *     s3c2410fb_check_var():
+ *     Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *     if it's too big, return -EINVAL.
+ *
+ */
+static int s3c2410fb_check_var(struct fb_var_screeninfo *var,
+                              struct fb_info *info)
+{
+       struct s3c2410fb_info *fbi = info->par;
+
+       dprintk("check_var(var=%p, info=%p)\n", var, info);
+
+       /* validate x/y resolution */
+
+       if (var->yres > fbi->mach_info->yres.max)
+               var->yres = fbi->mach_info->yres.max;
+       else if (var->yres < fbi->mach_info->yres.min)
+               var->yres = fbi->mach_info->yres.min;
+
+       if (var->xres > fbi->mach_info->xres.max)
+               var->yres = fbi->mach_info->xres.max;
+       else if (var->xres < fbi->mach_info->xres.min)
+               var->xres = fbi->mach_info->xres.min;
+
+       /* validate bpp */
+
+       if (var->bits_per_pixel > fbi->mach_info->bpp.max)
+               var->bits_per_pixel = fbi->mach_info->bpp.max;
+       else if (var->bits_per_pixel < fbi->mach_info->bpp.min)
+               var->bits_per_pixel = fbi->mach_info->bpp.min;
+
+       /* set r/g/b positions */
+
+       if (var->bits_per_pixel == 16) {
+               var->red.offset         = 11;
+               var->green.offset       = 5;
+               var->blue.offset        = 0;
+               var->red.length         = 5;
+               var->green.length       = 6;
+               var->blue.length        = 5;
+               var->transp.length      = 0;
+       } else {
+               var->red.length         = var->bits_per_pixel;
+               var->red.offset         = 0;
+               var->green.length       = var->bits_per_pixel;
+               var->green.offset       = 0;
+               var->blue.length        = var->bits_per_pixel;
+               var->blue.offset        = 0;
+               var->transp.length      = 0;
+       }
+
+       return 0;
+}
+
+/* s3c2410fb_activate_var
+ *
+ * activate (set) the controller from the given framebuffer
+ * information
+*/
+
+static int s3c2410fb_activate_var(struct s3c2410fb_info *fbi,
+                                 struct fb_var_screeninfo *var)
+{
+       fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK;
+
+       dprintk("%s: var->xres  = %d\n", __FUNCTION__, var->xres);
+       dprintk("%s: var->yres  = %d\n", __FUNCTION__, var->yres);
+       dprintk("%s: var->bpp   = %d\n", __FUNCTION__, var->bits_per_pixel);
+
+       switch (var->bits_per_pixel) {
+       case 1:
+               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP;
+               break;
+       case 2:
+               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP;
+               break;
+       case 4:
+               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP;
+               break;
+       case 8:
+               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP;
+               break;
+       case 16:
+               fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP;
+               break;
+       }
+
+       /* check to see if we need to update sync/borders */
+
+       if (!fbi->mach_info->fixed_syncs) {
+               dprintk("setting vert: up=%d, low=%d, sync=%d\n",
+                       var->upper_margin, var->lower_margin,
+                       var->vsync_len);
+
+               dprintk("setting horz: lft=%d, rt=%d, sync=%d\n",
+                       var->left_margin, var->right_margin,
+                       var->hsync_len);
+
+               fbi->regs.lcdcon2 =
+                       S3C2410_LCDCON2_VBPD(var->upper_margin - 1) |
+                       S3C2410_LCDCON2_VFPD(var->lower_margin - 1) |
+                       S3C2410_LCDCON2_VSPW(var->vsync_len - 1);
+
+               fbi->regs.lcdcon3 =
+                       S3C2410_LCDCON3_HBPD(var->right_margin - 1) |
+                       S3C2410_LCDCON3_HFPD(var->left_margin - 1);
+
+               fbi->regs.lcdcon4 &= ~S3C2410_LCDCON4_HSPW(0xff);
+               fbi->regs.lcdcon4 |=  S3C2410_LCDCON4_HSPW(var->hsync_len - 1);
+       }
+
+       /* update X/Y info */
+
+       fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff);
+       fbi->regs.lcdcon2 |=  S3C2410_LCDCON2_LINEVAL(var->yres - 1);
+
+       fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff);
+       fbi->regs.lcdcon3 |=  S3C2410_LCDCON3_HOZVAL(var->xres - 1);
+
+       if (var->pixclock > 0) {
+               int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock);
+
+               clkdiv = (clkdiv / 2) -1;
+               if (clkdiv < 0)
+                       clkdiv = 0;
+
+               fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff);
+               fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);
+       }
+
+       /* write new registers */
+
+       dprintk("new register set:\n");
+       dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);
+       dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);
+       dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);
+       dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);
+       dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);
+
+       writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+       writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+       writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+       writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+       writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+       /* set lcd address pointers */
+       s3c2410fb_set_lcdaddr(fbi);
+
+       writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+}
+
+
+/*
+ *      s3c2410fb_set_par - Optional function. Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ */
+static int s3c2410fb_set_par(struct fb_info *info)
+{
+       struct s3c2410fb_info *fbi = info->par;
+       struct fb_var_screeninfo *var = &info->var;
+
+       if (var->bits_per_pixel == 16)
+               fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR;
+       else
+               fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+       fbi->fb->fix.line_length     = (var->width*var->bits_per_pixel)/8;
+
+       /* activate this new configuration */
+
+       s3c2410fb_activate_var(fbi, var);
+       return 0;
+}
+
+static void schedule_palette_update(struct s3c2410fb_info *fbi,
+                                   unsigned int regno, unsigned int val)
+{
+       unsigned long flags;
+       unsigned long irqen;
+
+       local_irq_save(flags);
+
+       fbi->palette_buffer[regno] = val;
+
+       if (!fbi->palette_ready) {
+               fbi->palette_ready = 1;
+
+               /* enable IRQ */
+               irqen = readl(S3C2410_LCDINTMSK);
+               irqen &= ~S3C2410_LCDINT_FRSYNC;
+               writel(irqen, S3C2410_LCDINTMSK);
+       }
+
+       local_irq_restore(flags);
+}
+
+/* from pxafb.c */
+static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+static int s3c2410fb_setcolreg(unsigned regno,
+                              unsigned red, unsigned green, unsigned blue,
+                              unsigned transp, struct fb_info *info)
+{
+       struct s3c2410fb_info *fbi = info->par;
+       unsigned int val;
+
+       /* dprintk("setcol: regno=%d, rgb=%d,%d,%d\n", regno, red, green, blue); */
+
+       switch (fbi->fb->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               /* true-colour, use pseuo-palette */
+
+               if (regno < 16) {
+                       u32 *pal = fbi->fb->pseudo_palette;
+
+                       val  = chan_to_field(red,   &fbi->fb->var.red);
+                       val |= chan_to_field(green, &fbi->fb->var.green);
+                       val |= chan_to_field(blue,  &fbi->fb->var.blue);
+
+                       pal[regno] = val;
+               }
+               break;
+
+       case FB_VISUAL_PSEUDOCOLOR:
+               if (regno < 256) {
+                       /* currently assume RGB 5-6-5 mode */
+
+                       val  = ((red   >>  0) & 0xf800);
+                       val |= ((green >>  5) & 0x07e0);
+                       val |= ((blue  >> 11) & 0x001f);
+
+                       writel(val, S3C2410_TFTPAL(regno));
+                       schedule_palette_update(fbi, regno, val);
+               }
+
+               break;
+
+       default:
+               return 1;   /* unknown type */
+       }
+
+       return 0;
+}
+
+
+/**
+ *      s3c2410fb_blank
+ *     @blank_mode: the blank mode we want.
+ *     @info: frame buffer structure that represents a single frame buffer
+ *
+ *     Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *     blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *     video mode which doesn't support it. Implements VESA suspend
+ *     and powerdown modes on hardware that supports disabling hsync/vsync:
+ *     blank_mode == 2: suspend vsync
+ *     blank_mode == 3: suspend hsync
+ *     blank_mode == 4: powerdown
+ *
+ *     Returns negative errno on error, or zero on success.
+ *
+ */
+static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
+{
+       dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
+
+       if (mach_info == NULL)
+               return -EINVAL;
+
+       if (blank_mode == FB_BLANK_UNBLANK)
+               writel(0x0, S3C2410_TPAL);
+       else {
+               dprintk("setting TPAL to output 0x000000\n");
+               writel(S3C2410_TPAL_EN, S3C2410_TPAL);
+       }
+
+       return 0;
+}
+
+static int s3c2410fb_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%s\n", debug ? "on" : "off");
+}
+static int s3c2410fb_debug_store(struct device *dev, struct device_attribute *attr,
+                                          const char *buf, size_t len)
+{
+       if (mach_info == NULL)
+               return -EINVAL;
+
+       if (len < 1)
+               return -EINVAL;
+
+       if (strnicmp(buf, "on", 2) == 0 ||
+           strnicmp(buf, "1", 1) == 0) {
+               debug = 1;
+               printk(KERN_DEBUG "s3c2410fb: Debug On");
+       } else if (strnicmp(buf, "off", 3) == 0 ||
+                  strnicmp(buf, "0", 1) == 0) {
+               debug = 0;
+               printk(KERN_DEBUG "s3c2410fb: Debug Off");
+       } else {
+               return -EINVAL;
+       }
+
+       return len;
+}
+
+
+static DEVICE_ATTR(debug, 0666,
+                  s3c2410fb_debug_show,
+                  s3c2410fb_debug_store);
+
+static struct fb_ops s3c2410fb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = s3c2410fb_check_var,
+       .fb_set_par     = s3c2410fb_set_par,
+       .fb_blank       = s3c2410fb_blank,
+       .fb_setcolreg   = s3c2410fb_setcolreg,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_cursor      = soft_cursor,
+};
+
+
+/*
+ * s3c2410fb_map_video_memory():
+ *     Allocates the DRAM memory for the frame buffer.  This buffer is
+ *     remapped into a non-cached, non-buffered, memory region to
+ *     allow palette and pixel writes to occur without flushing the
+ *     cache.  Once this area is remapped, all virtual memory
+ *     access to the video memory should occur at the new region.
+ */
+static int __init s3c2410fb_map_video_memory(struct s3c2410fb_info *fbi)
+{
+       dprintk("map_video_memory(fbi=%p)\n", fbi);
+
+       fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);
+       fbi->map_cpu  = dma_alloc_writecombine(fbi->dev, fbi->map_size,
+                                              &fbi->map_dma, GFP_KERNEL);
+
+       fbi->map_size = fbi->fb->fix.smem_len;
+
+       if (fbi->map_cpu) {
+               /* prevent initial garbage on screen */
+               dprintk("map_video_memory: clear %p:%08x\n",
+                       fbi->map_cpu, fbi->map_size);
+               memset(fbi->map_cpu, 0xf0, fbi->map_size);
+
+               fbi->screen_dma         = fbi->map_dma;
+               fbi->fb->screen_base    = fbi->map_cpu;
+               fbi->fb->fix.smem_start  = fbi->screen_dma;
+
+               dprintk("map_video_memory: dma=%08x cpu=%p size=%08x\n",
+                       fbi->map_dma, fbi->map_cpu, fbi->fb->fix.smem_len);
+       }
+
+       return fbi->map_cpu ? 0 : -ENOMEM;
+}
+
+static inline void s3c2410fb_unmap_video_memory(struct s3c2410fb_info *fbi)
+{
+       dma_free_writecombine(fbi->dev,fbi->map_size,fbi->map_cpu, fbi->map_dma);
+}
+
+static inline void modify_gpio(void __iomem *reg,
+                              unsigned long set, unsigned long mask)
+{
+       unsigned long tmp;
+
+       tmp = readl(reg) & ~mask;
+       writel(tmp | set, reg);
+}
+
+
+/*
+ * s3c2410fb_init_registers - Initialise all LCD-related registers
+ */
+
+int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+{
+       unsigned long flags;
+
+       /* Initialise LCD with values from haret */
+
+       local_irq_save(flags);
+
+       /* modify the gpio(s) with interrupts set (bjd) */
+
+       modify_gpio(S3C2410_GPCUP,  mach_info->gpcup,  mach_info->gpcup_mask);
+       modify_gpio(S3C2410_GPCCON, mach_info->gpccon, mach_info->gpccon_mask);
+       modify_gpio(S3C2410_GPDUP,  mach_info->gpdup,  mach_info->gpdup_mask);
+       modify_gpio(S3C2410_GPDCON, mach_info->gpdcon, mach_info->gpdcon_mask);
+
+       local_irq_restore(flags);
+
+       writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+       writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);
+       writel(fbi->regs.lcdcon3, S3C2410_LCDCON3);
+       writel(fbi->regs.lcdcon4, S3C2410_LCDCON4);
+       writel(fbi->regs.lcdcon5, S3C2410_LCDCON5);
+
+       s3c2410fb_set_lcdaddr(fbi);
+
+       dprintk("LPCSEL    = 0x%08lx\n", mach_info->lpcsel);
+       writel(mach_info->lpcsel, S3C2410_LPCSEL);
+
+       dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL));
+
+       /* ensure temporary palette disabled */
+       writel(0x00, S3C2410_TPAL);
+
+       /* Enable video by setting the ENVID bit to 1 */
+       fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID;
+       writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
+       return 0;
+}
+
+static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi)
+{
+       unsigned int i;
+       unsigned long ent;
+
+       fbi->palette_ready = 0;
+
+       for (i = 0; i < 256; i++) {
+               if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR)
+                       continue;
+
+               writel(ent, S3C2410_TFTPAL(i));
+
+               /* it seems the only way to know exactly
+                * if the palette wrote ok, is to check
+                * to see if the value verifies ok
+                */
+
+               if (readw(S3C2410_TFTPAL(i)) == ent)
+                       fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+               else
+                       fbi->palette_ready = 1;   /* retry */
+       }
+}
+
+static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
+{
+       struct s3c2410fb_info *fbi = dev_id;
+       unsigned long lcdirq = readl(S3C2410_LCDINTPND);
+
+       if (lcdirq & S3C2410_LCDINT_FRSYNC) {
+               if (fbi->palette_ready)
+                       s3c2410fb_write_palette(fbi);
+
+               writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND);
+               writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static char driver_name[]="s3c2410fb";
+
+int __init s3c2410fb_probe(struct device *dev)
+{
+       struct s3c2410fb_info *info;
+       struct fb_info     *fbinfo;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct s3c2410fb_hw *mregs;
+       int ret;
+       int irq;
+       int i;
+
+       mach_info = dev->platform_data;
+       if (mach_info == NULL) {
+               dev_err(dev,"no platform data for lcd, cannot attach\n");
+               return -EINVAL;
+       }
+
+       mregs = &mach_info->regs;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "no irq for device\n");
+               return -ENOENT;
+       }
+
+       fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), dev);
+       if (!fbinfo) {
+               return -ENOMEM;
+       }
+
+
+       info = fbinfo->par;
+       info->fb = fbinfo;
+       dev_set_drvdata(dev, fbinfo);
+
+       s3c2410fb_init_registers(info);
+
+       dprintk("devinit\n");
+
+       strcpy(fbinfo->fix.id, driver_name);
+
+       memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));
+
+       info->mach_info             = dev->platform_data;
+
+       fbinfo->fix.type            = FB_TYPE_PACKED_PIXELS;
+       fbinfo->fix.type_aux        = 0;
+       fbinfo->fix.xpanstep        = 0;
+       fbinfo->fix.ypanstep        = 0;
+       fbinfo->fix.ywrapstep       = 0;
+       fbinfo->fix.accel           = FB_ACCEL_NONE;
+
+       fbinfo->var.nonstd          = 0;
+       fbinfo->var.activate        = FB_ACTIVATE_NOW;
+       fbinfo->var.height          = mach_info->height;
+       fbinfo->var.width           = mach_info->width;
+       fbinfo->var.accel_flags     = 0;
+       fbinfo->var.vmode           = FB_VMODE_NONINTERLACED;
+
+       fbinfo->fbops               = &s3c2410fb_ops;
+       fbinfo->flags               = FBINFO_FLAG_DEFAULT;
+       fbinfo->pseudo_palette      = &info->pseudo_pal;
+
+       fbinfo->var.xres            = mach_info->xres.defval;
+       fbinfo->var.xres_virtual    = mach_info->xres.defval;
+       fbinfo->var.yres            = mach_info->yres.defval;
+       fbinfo->var.yres_virtual    = mach_info->yres.defval;
+       fbinfo->var.bits_per_pixel  = mach_info->bpp.defval;
+
+       fbinfo->var.upper_margin    = S3C2410_LCDCON2_GET_VBPD(mregs->lcdcon2) +1;
+       fbinfo->var.lower_margin    = S3C2410_LCDCON2_GET_VFPD(mregs->lcdcon2) +1;
+       fbinfo->var.vsync_len       = S3C2410_LCDCON2_GET_VSPW(mregs->lcdcon2) + 1;
+
+       fbinfo->var.left_margin     = S3C2410_LCDCON3_GET_HFPD(mregs->lcdcon3) + 1;
+       fbinfo->var.right_margin    = S3C2410_LCDCON3_GET_HBPD(mregs->lcdcon3) + 1;
+       fbinfo->var.hsync_len       = S3C2410_LCDCON4_GET_HSPW(mregs->lcdcon4) + 1;
+
+       fbinfo->var.red.offset      = 11;
+       fbinfo->var.green.offset    = 5;
+       fbinfo->var.blue.offset     = 0;
+       fbinfo->var.transp.offset   = 0;
+       fbinfo->var.red.length      = 5;
+       fbinfo->var.green.length    = 6;
+       fbinfo->var.blue.length     = 5;
+       fbinfo->var.transp.length   = 0;
+       fbinfo->fix.smem_len        =   mach_info->xres.max *
+                                       mach_info->yres.max *
+                                       mach_info->bpp.max / 8;
+
+       for (i = 0; i < 256; i++)
+               info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
+
+       if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) {
+               ret = -EBUSY;
+               goto dealloc_fb;
+       }
+
+
+       dprintk("got LCD region\n");
+
+       ret = request_irq(irq, s3c2410fb_irq, SA_INTERRUPT, pdev->name, info);
+       if (ret) {
+               dev_err(dev, "cannot get irq %d - err %d\n", irq, ret);
+               ret = -EBUSY;
+               goto release_mem;
+       }
+
+       info->clk = clk_get(NULL, "lcd");
+       if (!info->clk || IS_ERR(info->clk)) {
+               printk(KERN_ERR "failed to get lcd clock source\n");
+               ret = -ENOENT;
+               goto release_irq;
+       }
+
+       clk_use(info->clk);
+       clk_enable(info->clk);
+       dprintk("got and enabled clock\n");
+
+       msleep(1);
+
+       /* Initialize video memory */
+       ret = s3c2410fb_map_video_memory(info);
+       if (ret) {
+               printk( KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+               ret = -ENOMEM;
+               goto release_clock;
+       }
+       dprintk("got video memory\n");
+
+       ret = s3c2410fb_init_registers(info);
+
+       ret = s3c2410fb_check_var(&fbinfo->var, fbinfo);
+
+       ret = register_framebuffer(fbinfo);
+       if (ret < 0) {
+               printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
+               goto free_video_memory;
+       }
+
+       /* create device files */
+       device_create_file(dev, &dev_attr_debug);
+
+       printk(KERN_INFO "fb%d: %s frame buffer device\n",
+               fbinfo->node, fbinfo->fix.id);
+
+       return 0;
+
+free_video_memory:
+       s3c2410fb_unmap_video_memory(info);
+release_clock:
+       clk_disable(info->clk);
+       clk_unuse(info->clk);
+       clk_put(info->clk);
+release_irq:
+       free_irq(irq,info);
+release_mem:
+       release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+dealloc_fb:
+       framebuffer_release(fbinfo);
+       return ret;
+}
+
+/* s3c2410fb_stop_lcd
+ *
+ * shutdown the lcd controller
+*/
+
+static void s3c2410fb_stop_lcd(void)
+{
+       unsigned long flags;
+       unsigned long tmp;
+
+       local_irq_save(flags);
+
+       tmp = readl(S3C2410_LCDCON1);
+       writel(tmp & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+
+       local_irq_restore(flags);
+}
+
+/*
+ *  Cleanup
+ */
+static int s3c2410fb_remove(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct fb_info     *fbinfo = dev_get_drvdata(dev);
+       struct s3c2410fb_info *info = fbinfo->par;
+       int irq;
+
+       s3c2410fb_stop_lcd();
+       msleep(1);
+
+       s3c2410fb_unmap_video_memory(info);
+
+       if (info->clk) {
+               clk_disable(info->clk);
+               clk_unuse(info->clk);
+               clk_put(info->clk);
+               info->clk = NULL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       free_irq(irq,info);
+       release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD);
+       unregister_framebuffer(fbinfo);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* suspend and resume support for the lcd controller */
+
+static int s3c2410fb_suspend(struct device *dev, pm_message_t state, u32 level)
+{
+       struct fb_info     *fbinfo = dev_get_drvdata(dev);
+       struct s3c2410fb_info *info = fbinfo->par;
+
+       if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN) {
+               s3c2410fb_stop_lcd();
+
+               /* sleep before disabling the clock, we need to ensure
+                * the LCD DMA engine is not going to get back on the bus
+                * before the clock goes off again (bjd) */
+
+               msleep(1);
+               clk_disable(info->clk);
+       }
+
+       return 0;
+}
+
+static int s3c2410fb_resume(struct device *dev, u32 level)
+{
+       struct fb_info     *fbinfo = dev_get_drvdata(dev);
+       struct s3c2410fb_info *info = fbinfo->par;
+
+       if (level == RESUME_ENABLE) {
+               clk_enable(info->clk);
+               msleep(1);
+
+               s3c2410fb_init_registers(info);
+
+       }
+
+       return 0;
+}
+
+#else
+#define s3c2410fb_suspend NULL
+#define s3c2410fb_resume  NULL
+#endif
+
+static struct device_driver s3c2410fb_driver = {
+       .name           = "s3c2410-lcd",
+       .bus            = &platform_bus_type,
+       .probe          = s3c2410fb_probe,
+       .suspend        = s3c2410fb_suspend,
+       .resume         = s3c2410fb_resume,
+       .remove         = s3c2410fb_remove
+};
+
+int __devinit s3c2410fb_init(void)
+{
+       return driver_register(&s3c2410fb_driver);
+}
+
+static void __exit s3c2410fb_cleanup(void)
+{
+       driver_unregister(&s3c2410fb_driver);
+}
+
+
+module_init(s3c2410fb_init);
+module_exit(s3c2410fb_cleanup);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, Ben Dooks <ben-linux@fluff.org>");
+MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
new file mode 100644 (file)
index 0000000..be40968
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * linux/drivers/s3c2410fb.h
+ * Copyright (c) Arnaud Patard
+ *
+ * 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.
+ *
+ *         S3C2410 LCD Controller Frame Buffer Driver
+ *         based on skeletonfb.c, sa1100fb.h
+ *
+ * ChangeLog
+ *
+ * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *      - Moved dprintk to s3c2410fb.c
+ *
+ * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - Renamed from h1940fb.h to s3c2410fb.h
+ *     - Chenged h1940 to s3c2410
+ *
+ * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org>
+ *     - First version
+ */
+
+#ifndef __S3C2410FB_H
+#define __S3C2410FB_H
+
+struct s3c2410fb_info {
+       struct fb_info          *fb;
+       struct device           *dev;
+       struct clk              *clk;
+
+       struct s3c2410fb_mach_info *mach_info;
+
+       /* raw memory addresses */
+       dma_addr_t              map_dma;        /* physical */
+       u_char *                map_cpu;        /* virtual */
+       u_int                   map_size;
+
+       struct s3c2410fb_hw     regs;
+
+       /* addresses of pieces placed in raw buffer */
+       u_char *                screen_cpu;     /* virtual address of buffer */
+       dma_addr_t              screen_dma;     /* physical address of buffer */
+       unsigned int            palette_ready;
+
+       /* keep these registers in case we need to re-write palette */
+       u32                     palette_buffer[256];
+       u32                     pseudo_pal[16];
+};
+
+#define PALETTE_BUFF_CLEAR (0x80000000)        /* entry is clear/invalid */
+
+int s3c2410fb_init(void);
+
+#endif
index 847698b5cfe7d3b2c1e518eedc5f910d451db452..959404ad68f433803ba06e824f5b427b4e143cb4 100644 (file)
@@ -259,8 +259,9 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
        return buf;
 }
 
-int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
+int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
 {
+       struct savagefb_par *par = info->par;
        u8 *edid = NULL;
        int i;
 
@@ -270,12 +271,19 @@ int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
                if (edid)
                        break;
        }
+
+       if (!edid) {
+               /* try to get from firmware */
+               edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+               if (edid)
+                       memcpy(edid, fb_firmware_edid(info->device),
+                              EDID_LENGTH);
+       }
+
        if (out_edid)
                *out_edid = edid;
-       if (!edid)
-               return 1;
 
-       return 0;
+       return (edid) ? 0 : 1;
 }
 
 MODULE_LICENSE("GPL");
index 8594b1e42d7189f2ff455035378f5bed6d13aa44..d6f94742c9f27bbe49421452797d63b56a3033f2 100644 (file)
@@ -60,6 +60,7 @@
 
 #define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
 
+#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))
 
 /* Chip tags.  These are used to group the adapters into
  * related families.
@@ -73,6 +74,8 @@ typedef enum {
   S3_PROSAVAGE,
   S3_SUPERSAVAGE,
   S3_SAVAGE2000,
+  S3_PROSAVAGEDDR,
+  S3_TWISTER,
   S3_LAST
 } savage_chipset;
 
@@ -128,6 +131,10 @@ typedef enum {
 #define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
 #define BCI_CMD_SEND_COLOR           0x00008000
 
+#define DISP_CRT     1
+#define DISP_LCD     2
+#define DISP_DFP     3
+
 struct xtimings {
        unsigned int Clock;
        unsigned int HDisplay;
@@ -166,6 +173,10 @@ struct savagefb_par {
        struct savagefb_i2c_chan chan;
        unsigned char   *edid;
        u32 pseudo_palette[16];
+       int pm_state;
+       int display_type;
+       int dvi;
+       int crtonly;
        int dacSpeedBpp;
        int maxClock;
        int minClock;
@@ -338,7 +349,7 @@ do {                       \
        } \
 }
 
-extern int savagefb_probe_i2c_connector(struct savagefb_par *par,
+extern int savagefb_probe_i2c_connector(struct fb_info *info,
                                        u8 **out_edid);
 extern void savagefb_create_i2c_busses(struct fb_info *info);
 extern void savagefb_delete_i2c_busses(struct fb_info *info);
index 117ad42f120d9c867599a36bcd0a804045732246..b5ca3ef8271f383c0a59b738d072fca167a182b6 100644 (file)
@@ -1400,6 +1400,58 @@ static int savagefb_pan_display (struct fb_var_screeninfo *var,
        return 0;
 }
 
+static int savagefb_blank(int blank, struct fb_info *info)
+{
+       struct savagefb_par *par = info->par;
+       u8 sr8 = 0, srd = 0;
+
+       if (par->display_type == DISP_CRT) {
+               vga_out8(0x3c4, 0x08);
+               sr8 = vga_in8(0x3c5);
+               sr8 |= 0x06;
+               vga_out8(0x3c5, sr8);
+               vga_out8(0x3c4, 0x0d);
+               srd = vga_in8(0x3c5);
+               srd &= 0x03;
+
+               switch (blank) {
+               case FB_BLANK_UNBLANK:
+               case FB_BLANK_NORMAL:
+                       break;
+               case FB_BLANK_VSYNC_SUSPEND:
+                       srd |= 0x10;
+                       break;
+               case FB_BLANK_HSYNC_SUSPEND:
+                       srd |= 0x40;
+                       break;
+               case FB_BLANK_POWERDOWN:
+                       srd |= 0x50;
+                       break;
+               }
+
+               vga_out8(0x3c4, 0x0d);
+               vga_out8(0x3c5, srd);
+       }
+
+       if (par->display_type == DISP_LCD ||
+           par->display_type == DISP_DFP) {
+               switch(blank) {
+               case FB_BLANK_UNBLANK:
+               case FB_BLANK_NORMAL:
+                       vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+                       vga_out8(0x3c5, vga_in8(0x3c5) | 0x10);
+                       break;
+               case FB_BLANK_VSYNC_SUSPEND:
+               case FB_BLANK_HSYNC_SUSPEND:
+               case FB_BLANK_POWERDOWN:
+                       vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
+                       vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10);
+                       break;
+               }
+       }
+
+       return (blank == FB_BLANK_NORMAL) ? 1 : 0;
+}
 
 static struct fb_ops savagefb_ops = {
        .owner          = THIS_MODULE,
@@ -1407,6 +1459,7 @@ static struct fb_ops savagefb_ops = {
        .fb_set_par     = savagefb_set_par,
        .fb_setcolreg   = savagefb_setcolreg,
        .fb_pan_display = savagefb_pan_display,
+       .fb_blank       = savagefb_blank,
 #if defined(CONFIG_FB_SAVAGE_ACCEL)
        .fb_fillrect    = savagefb_fillrect,
        .fb_copyarea    = savagefb_copyarea,
@@ -1583,8 +1636,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
        static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
        static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
        static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
-
-       int videoRam, videoRambytes;
+       int videoRam, videoRambytes, dvi;
 
        DBG("savage_init_hw");
 
@@ -1705,6 +1757,30 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
        printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
                par->MCLK);
 
+       /* check for DVI/flat panel */
+       dvi = 0;
+
+       if (par->chip == S3_SAVAGE4) {
+               unsigned char sr30 = 0x00;
+
+               vga_out8(0x3c4, 0x30);
+               /* clear bit 1 */
+               vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02);
+               sr30 = vga_in8(0x3c5);
+               if (sr30 & 0x02 /*0x04 */) {
+                       dvi = 1;
+                       printk("savagefb: Digital Flat Panel Detected\n");
+               }
+       }
+
+       if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+           (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
+               par->display_type = DISP_LCD;
+       else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
+               par->display_type = DISP_DFP;
+       else
+               par->display_type = DISP_CRT;
+
        /* Check LCD panel parrmation */
 
        if (par->chip == S3_SAVAGE_MX) {
@@ -1759,7 +1835,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
                        par->SavagePanelWidth = panelX;
                        par->SavagePanelHeight = panelY;
 
-               }
+               } else
+                       par->display_type = DISP_CRT;
        }
 
        savage_get_default_par (par);
@@ -1845,15 +1922,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
                snprintf (info->fix.id, 16, "ProSavageKM");
                break;
        case FB_ACCEL_S3TWISTER_P:
-               par->chip = S3_PROSAVAGE;
+               par->chip = S3_TWISTER;
                snprintf (info->fix.id, 16, "TwisterP");
                break;
        case FB_ACCEL_S3TWISTER_K:
-               par->chip = S3_PROSAVAGE;
+               par->chip = S3_TWISTER;
                snprintf (info->fix.id, 16, "TwisterK");
                break;
        case FB_ACCEL_PROSAVAGE_DDR:
-               par->chip = S3_PROSAVAGE;
+               par->chip = S3_PROSAVAGEDDR;
                snprintf (info->fix.id, 16, "ProSavageDDR");
                break;
        case FB_ACCEL_PROSAVAGE_DDRK:
@@ -1899,12 +1976,11 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
                info->pixmap.buf_align = 4;
                info->pixmap.access_align = 32;
 
-               fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+               err = fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+               if (!err)
                info->flags |= FBINFO_HWACCEL_COPYAREA |
                               FBINFO_HWACCEL_FILLRECT |
                               FBINFO_HWACCEL_IMAGEBLIT;
-
-               err = 0;
        }
 #endif
        return err;
@@ -1932,14 +2008,14 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
        if (err)
                goto failed_enable;
 
-       if (pci_request_regions(dev, "savagefb")) {
+       if ((err = pci_request_regions(dev, "savagefb"))) {
                printk(KERN_ERR "cannot request PCI regions\n");
                goto failed_enable;
        }
 
        err = -ENOMEM;
 
-       if (savage_init_fb_info(info, dev, id))
+       if ((err = savage_init_fb_info(info, dev, id)))
                goto failed_init;
 
        err = savage_map_mmio(info);
@@ -1947,6 +2023,7 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
                goto failed_mmio;
 
        video_len = savage_init_hw(par);
+       /* FIXME: cant be negative */
        if (video_len < 0) {
                err = video_len;
                goto failed_mmio;
@@ -1959,7 +2036,8 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
        INIT_LIST_HEAD(&info->modelist);
 #if defined(CONFIG_FB_SAVAGE_I2C)
        savagefb_create_i2c_busses(info);
-       savagefb_probe_i2c_connector(par, &par->edid);
+       savagefb_probe_i2c_connector(info, &par->edid);
+       kfree(par->edid);
        fb_edid_to_monspecs(par->edid, &info->monspecs);
        fb_videomode_to_modelist(info->monspecs.modedb,
                                 info->monspecs.modedb_len,
@@ -2111,13 +2189,30 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
 
        DBG("savagefb_suspend");
 
+
+       par->pm_state = state.event;
+
+       /*
+        * For PM_EVENT_FREEZE, do not power down so the console
+        * can remain active.
+        */
+       if (state.event == PM_EVENT_FREEZE) {
+               dev->dev.power.power_state = state;
+               return 0;
+       }
+
        acquire_console_sem();
-       fb_set_suspend(info, pci_choose_state(dev, state));
-       savage_disable_mmio(par);
-       release_console_sem();
+       fb_set_suspend(info, 1);
 
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       savagefb_blank(FB_BLANK_POWERDOWN, info);
+       savage_disable_mmio(par);
+       pci_save_state(dev);
        pci_disable_device(dev);
        pci_set_power_state(dev, pci_choose_state(dev, state));
+       release_console_sem();
 
        return 0;
 }
@@ -2127,22 +2222,34 @@ static int savagefb_resume (struct pci_dev* dev)
        struct fb_info *info =
                (struct fb_info *)pci_get_drvdata(dev);
        struct savagefb_par *par = (struct savagefb_par *)info->par;
+       int cur_state = par->pm_state;
 
        DBG("savage_resume");
 
-       pci_set_power_state(dev, 0);
-       pci_restore_state(dev);
-       if(pci_enable_device(dev))
-               DBG("err");
+       par->pm_state = PM_EVENT_ON;
 
-       SavagePrintRegs();
+       /*
+        * The adapter was not powered down coming back from a
+        * PM_EVENT_FREEZE.
+        */
+       if (cur_state == PM_EVENT_FREEZE) {
+               pci_set_power_state(dev, PCI_D0);
+               return 0;
+       }
 
        acquire_console_sem();
 
+       pci_set_power_state(dev, PCI_D0);
+       pci_restore_state(dev);
+
+       if(pci_enable_device(dev))
+               DBG("err");
+
+       pci_set_master(dev);
        savage_enable_mmio(par);
        savage_init_hw(par);
        savagefb_set_par (info);
-
+       savagefb_blank(FB_BLANK_UNBLANK, info);
        fb_set_suspend (info, 0);
        release_console_sem();
 
@@ -2276,3 +2383,6 @@ static int __init savagefb_init(void)
 
 module_init(savagefb_init);
 module_exit(savage_done);
+
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
index b6d5c71b2563099164c9219a43a7159131f4984c..e4b4a2626da464f894bdd790c8cbcb1d13891609 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * Register settings for SiS 300 series
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-static const SiS_StStruct  SiS300_SModeIDTable[] =
-{
-       {0x01,0x9208,0x01,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x01,0x1210,0x14,0x01,0x01,0x00,0x00,0x00, 0},
-       {0x01,0x1010,0x17,0x02,0x02,0x00,0x00,0x00, 0},
-       {0x03,0x8208,0x03,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x03,0x0210,0x16,0x01,0x01,0x00,0x00,0x00, 0},
-       {0x03,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0},
-       {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x07,0x0000,0x07,0x03,0x03,0x00,0x00,0x00, 0},
-       {0x07,0x0000,0x19,0x02,0x02,0x00,0x00,0x00, 0},
-       {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x00, 0},
-       {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x00, 0},
-       {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x00, 0},
-       {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x00, 0},
-       {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x00, 0},
-       {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x00, 0},
-       {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x00, 0},
-       {0xff,     0,   0,   0,   0,   0,   0,   0, 0}
-};
-
-static const SiS_ExtStruct  SiS300_EModeIDTable[] =
+static const struct SiS_Ext SiS300_EModeIDTable[] =
 {
        {0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x? */
        {0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
@@ -110,7 +86,7 @@ static const SiS_ExtStruct  SiS300_EModeIDTable[] =
        {0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x8  */
        {0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x32 */
        {0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x16 */
-       {0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
+       {0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
        {0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
        {0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x32 */
        {0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
@@ -119,8 +95,8 @@ static const SiS_ExtStruct  SiS300_EModeIDTable[] =
        {0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
        {0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
        {0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
-       {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 - not in BIOS! */
-       {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 - not in BIOS! */
+       {0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 */
+       {0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 */
        {0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x8 */
        {0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x8 */
        {0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x16 */
@@ -166,77 +142,77 @@ static const SiS_ExtStruct  SiS300_EModeIDTable[] =
        {0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
 };
 
-static const SiS_Ext2Struct  SiS300_RefIndex[] =
-{
-       {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0}, /* 00 */
-       {0x0467,0x0e,0x44,0x05,0x05,0x6a, 800, 600, 0}, /* 01 */
-       {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0}, /* 02 - CRT1CRTC was 0x4f */
-       {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0}, /* 03 */
-       {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0}, /* 04 */
-       {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0}, /* 05 */
-       {0x0047,0x11,0x4e,0x00,0x05,0x6a, 800, 600, 0}, /* 06 - CRT1CRTC was 0x51 */
-       {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0}, /* 07 */
-       {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0}, /* 08 */
-       {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0}, /* 09 */
-       {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0}, /* 0a */
-       {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0}, /* 0b */
-       {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0}, /* 0c */
-       {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0}, /* 0d */
-       {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0}, /* 0e */
-       {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0}, /* 0f */
-       {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0}, /* 10 */
-       {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0}, /* 11 */
-       {0x006f,0x32,0x03,0x06,0x14,0x32, 720, 576, 0}, /* 12 */
-       {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0}, /* 13 */
-        {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0}, /* 14 */
-       {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0}, /* 15 - CRT1CRTC was 0x97 */
-       {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0}, /* 16 */
-       {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0}, /* 17 - CRT1CRTC was 0x59 */
-       {0x0047,0x1a,0x52,0x00,0x06,0x37,1024, 768, 0}, /* 18 */
-       {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0}, /* 19 - CRT1CRTC was 0x5b */
-       {0x0387,0x1c,0x4d,0x00,0x07,0x3a,1280,1024, 0}, /* 1a - CRT1CRTC was 0x5c */
-       {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0}, /* 1b */
-       {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0}, /* 1c */
-       {0x0007,0x1f,0x98,0x00,0x07,0x3a,1280,1024, 0}, /* 1d */
-       {0x0007,0x20,0x59,0x00,0x00,0x3c,1600,1200, 0}, /* 1e - CRT1CRTC was 0x60 */
-       {0x0007,0x21,0x5a,0x00,0x00,0x3c,1600,1200, 0}, /* 1f */
-       {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0}, /* 20 */
-       {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0}, /* 21 - CRT1CRTC was 0x63 */
-       {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0}, /* 22 */
-       {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0}, /* 23 */
-       {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0}, /* 24 */
-       {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0}, /* 25 */
-       {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0}, /* 26 */  /* was c077 */
-       {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0}, /* 27 */
-       {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0}, /* 28 */
-       {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0}, /* 29 - 1280x960-60 */
-       {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0}, /* 2a - 1280x960-85 */
-       {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0}, /* 2b */
-       {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0}, /* 2c */        /* VCLK 0x09 */
-       {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0}, /* 2d */
-       {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0}, /* 2e */
-       {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0}, /* 2f */
-       {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0}, /* 30 */
-       {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0}, /* 31 */
-       {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0}, /* 32 */
-       {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0}, /* 33 */
-       {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0}, /* 34 */
-       {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0}, /* 35 */
-       {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0}, /* 36 1152x864-60Hz  */
-       {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0}, /* 37 1152x864-75Hz */
-       {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0}, /* 38 1152x864-85Hz */
-       {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0}, /* 39 848x480-38Hzi */
-       {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0}, /* 3a 848x480-60Hz  */
-       {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3b 856x480-38Hzi */
-       {0xc047,0x42,0x28,0x00,0x17,0x3f, 856, 480, 0}, /* 3c 856x480-60Hz  */
-       {0x0067,0x43,0x3e,0x0c,0x1b,0x48,1360, 768, 0}, /* 3d 1360x768-60Hz */
-       {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0}, /* 3e 1280x768-60Hz */
-       {0x006f,0x47,0x03,0x06,0x15,0x5f, 768, 576, 0}, /* 3f 768x576 */
-       {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0}, /* 40 1360x1024-59Hz (BARCO1366 only) */
-       {0xffff,   0,   0,   0,   0,   0,   0,   0, 0}
-};
-
-static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
+static const struct SiS_Ext2 SiS300_RefIndex[] =
+{
+       {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 00 */
+       {0x0467,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 01 */
+       {0x0067,0x0f,0x07,0x48,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 02 - CRT1CRTC was 0x4f */
+       {0x0067,0x10,0x06,0x8b,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 03 */
+       {0x0147,0x11,0x08,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 04 */
+       {0x0147,0x12,0x0c,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 05 */
+       {0x0047,0x11,0x0e,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 06 - CRT1CRTC was 0x51 */
+       {0x0047,0x11,0x13,0x00,0x05,0x6a, 800, 600, 0, 0x00, 0x00}, /* 07 */
+       {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 08 */
+       {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 09 */
+       {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0a */
+       {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0b */
+       {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0c */
+       {0xc047,0x0a,0x08,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0d */
+       {0xc047,0x0b,0x0a,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0e */
+       {0xc047,0x0c,0x10,0x00,0x04,0x2e, 640, 480, 0, 0x00, 0x00}, /* 0f */
+       {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0, 0x4a, 0x49}, /* 10 */
+       {0xc06f,0x31,0x01,0x06,0x13,0x31, 720, 480, 0, 0x00, 0x00}, /* 11 */
+       {0x006f,0x32,0x4a,0x06,0x14,0x32, 720, 576, 0, 0x00, 0x00}, /* 12 */ /* 4a was 03 */
+       {0x0187,0x15,0x05,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 13 */
+       {0xc877,0x16,0x09,0x06,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 14 */
+       {0xc067,0x17,0x0b,0x49,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 15 - CRT1CRTC was 0x97 */
+       {0x0267,0x18,0x0d,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 16 */
+       {0x0047,0x19,0x11,0x8c,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 17 - CRT1CRTC was 0x59 */
+       {0x0047,0x1a,0x12,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 18 */
+       {0x0007,0x1b,0x16,0x00,0x06,0x37,1024, 768, 0, 0x00, 0x00}, /* 19 - CRT1CRTC was 0x5b */
+       {0x0387,0x1c,0x0d,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1a - CRT1CRTC was 0x5c */
+       {0x0077,0x1d,0x14,0x07,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1b */
+       {0x0047,0x1e,0x17,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1c */
+       {0x0007,0x1f,0x18,0x00,0x07,0x3a,1280,1024, 0, 0x00, 0x00}, /* 1d */
+       {0x0007,0x20,0x19,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1e - CRT1CRTC was 0x60 */
+       {0x0007,0x21,0x1a,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 1f */
+       {0x0007,0x22,0x1b,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 20 */
+       {0x0007,0x23,0x1d,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 21 - CRT1CRTC was 0x63 */
+       {0x0007,0x24,0x1e,0x00,0x00,0x3c,1600,1200, 0, 0x00, 0x00}, /* 22 */
+       {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0, 0x4b, 0x4b}, /* 23 */
+       {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0, 0x00, 0x00}, /* 24 */
+       {0x0077,0x02,0x04,0x05,0x05,0x51, 400, 300, 0, 0x00, 0x00}, /* 25 */
+       {0xc877,0x03,0x09,0x06,0x06,0x52, 512, 384, 0, 0x00, 0x00}, /* 26 */  /* was c077 */
+       {0x8207,0x25,0x1f,0x00,0x00,0x68,1920,1440, 0, 0x00, 0x00}, /* 27 */
+       {0x0007,0x26,0x20,0x00,0x00,0x6c,2048,1536, 0, 0x00, 0x00}, /* 28 */
+       {0x0067,0x27,0x14,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 29 - 1280x960-60 */
+       {0x0027,0x45,0x3c,0x08,0x0a,0x6e,1280, 960, 0, 0x00, 0x00}, /* 2a - 1280x960-85 */
+       {0xc077,0x33,0x09,0x06,0x00,0x20,1024, 600, 0, 0x00, 0x00}, /* 2b */
+       {0xc077,0x34,0x0b,0x06,0x00,0x23,1152, 768, 0, 0x00, 0x00}, /* 2c */    /* VCLK 0x09 */
+       {0x0077,0x35,0x27,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2d */
+       {0x0047,0x36,0x37,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2e */
+       {0x0047,0x37,0x08,0x08,0x18,0x70, 800, 480, 0, 0x00, 0x00}, /* 2f */
+       {0x0077,0x38,0x09,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 30 */
+       {0x0047,0x39,0x38,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 31 */
+       {0x0047,0x3a,0x11,0x09,0x19,0x71,1024, 576, 0, 0x00, 0x00}, /* 32 */
+       {0x0077,0x3b,0x39,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 33 */
+       {0x0047,0x3c,0x3a,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 34 */
+       {0x0007,0x3d,0x3b,0x0a,0x0c,0x75,1280, 720, 0, 0x00, 0x00}, /* 35 */
+       {0x0067,0x49,0x35,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 36 1152x864-60Hz  */
+       {0x0067,0x3e,0x34,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 37 1152x864-75Hz */
+       {0x0047,0x44,0x3a,0x06,0x1a,0x29,1152, 864, 0, 0x00, 0x00}, /* 38 1152x864-85Hz */
+       {0x00c7,0x3f,0x28,0x00,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 39 848x480-38Hzi */
+       {0xc067,0x40,0x3d,0x0b,0x16,0x39, 848, 480, 0, 0x00, 0x00}, /* 3a 848x480-60Hz  */
+       {0x00c7,0x41,0x28,0x00,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3b 856x480-38Hzi */
+       {0xc067,0x42,0x28,0x0c,0x17,0x3f, 856, 480, 0, 0x00, 0x00}, /* 3c 856x480-60Hz  */
+       {0x0067,0x43,0x3e,0x0d,0x1b,0x48,1360, 768, 0, 0x00, 0x00}, /* 3d 1360x768-60Hz */
+       {0x0077,0x46,0x3f,0x08,0x08,0x55,1280, 768, 0, 0x00, 0x00}, /* 3e 1280x768-60Hz */
+       {0x006f,0x47,0x4c,0x06,0x15,0x5f, 768, 576, 0, 0x00, 0x00}, /* 3f 768x576 */
+       {0x0027,0x48,0x13,0x08,0x00,0x67,1360,1024, 0, 0x00, 0x00}, /* 40 1360x1024-59Hz (BARCO1366 only) */
+       {0xffff,   0,   0,   0,   0,   0,   0,   0, 0, 0x00, 0x00}
+};
+
+static const struct SiS_VBMode SiS300_VBModeIDTable[] =
 {
        {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
        {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
@@ -303,53 +279,26 @@ static const SiS_VBModeStruct SiS300_VBModeIDTable[] =
        {0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
 };
 
-static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
+static const struct SiS_CRT1Table SiS300_CRT1Table[] =
 {
-#if 1
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,    /* 0x00 - 320x200 */
   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,     /* HRE [4],[15] is invalid - but correcting it does not work */
   0x00}},
-#endif
-#if 0
- {{0x2d,0x27,0x27,0x91,0x2c,0x92,0xbf,0x1f,    /* 0x00 - corrected 320x200-72 - does not work */
-  0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x04,
-  0x00}},
-#endif
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,    /* 0x01 */
   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,     /* HRE [4],[15] is invalid - but correcting it does not work */
   0x00}},
-#if 0
- {{0x2d,0x27,0x27,0x91,0x2c,0x92,0x0b,0x3e,    /* 0x01 - corrected 320x240-60 - does not work */
-  0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x04,
-  0x00}},
-#endif
  {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,    /* 0x02 */
   0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
   0x01}},
-#if 0
- {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,    /* 0x02 - corrected 400x300-60 */
-  0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
-  0x01}},
-#endif
  {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
   0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
   0x01}},
  {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
   0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
   0x00}},
-#if 0  
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,    /* 0x05 */
-  0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
-  0x00}},
-#endif
  {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
   0x00}},
-#if 0
- {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e,    /* 0x06 */
-  0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
-  0x00}},
-#endif  
  {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* 0x06 - corrected 640x480-72 */
   0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
   0x00}},
@@ -359,19 +308,9 @@ static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
  {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
   0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
   0x00}},
-#if 0  
- {{0x66,0x4f,0x4f,0x86,0x56,0x9e,0x03,0x3e,    /* 0x09 */
-  0xe4,0x87,0xdf,0xdf,0x04,0x00,0x00,0x01,
-  0x00}},
-#endif
  {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e,    /* 0x09 - corrected 640x480-100 */
   0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
   0x00}},
-#if 0  
- {{0x6c,0x4f,0x4f,0x83,0x59,0x9e,0x00,0x3e,    /* 0x0a */
-  0xe5,0x8d,0xdf,0xdf,0x01,0x00,0x00,0x01,
-  0x00}},
-#endif    
  {{0x67,0x4f,0x4f,0x8b,0x57,0x83,0x10,0x3e,    /* 0x0a - corrected 640x480-120 */
   0xe7,0x8d,0xdf,0xe6,0x11,0x00,0x00,0x05,
   0x00}},
@@ -459,11 +398,6 @@ static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
  {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
   0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
   0x00}},
-#if 0  
- {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef,  /* 0x27: 1280x960-70 - invalid! */
-  0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07,
-  0x01}},
-#endif  
  {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,  /* 0x27: 1280x960-60 - correct */
   0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
   0x01}},
@@ -497,9 +431,9 @@ static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
  {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
   0x00}},
- {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0,  /* 0x32 */
-  0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
-  0x01}},
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,  /* 0x32: 720x576, corrected to 60Hz */
+  0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+  0x41}},
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,  /* 0x33 - 1024x600 */
   0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
   0x01}},
@@ -560,18 +494,24 @@ static const SiS_CRT1TableStruct  SiS300_CRT1Table[] =
  {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x20,0xf5,  /* 1280x768-60 */
    0x03,0x88,0xff,0xff,0x21,0x10,0x00,0x07,
    0x01}}, /* 0x46 */
- {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0,  /* 768x576 */
-   0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
-   0x01}}, /* 0x47 */
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0,  /* 768x576, corrected to 60Hz */
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}}, /* 0x47 */
  {{0xce,0xa9,0xa9,0x92,0xb1,0x07,0x28,0x52,  /* 1360x1024 (Barco iQ Pro R300) */
    0x02,0x8e,0xff,0x00,0x29,0x0d,0x00,0x03,
    0x00}}, /* 0x48 */
  {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff,  /* 1152x864-60 */
    0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
-   0x41}}  /* 0x49 */
+   0x41}}, /* 0x49 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+   0x40}}, /* 0x4a */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+   0x00}}  /* 0x4b */
 };
 
-static const SiS_MCLKDataStruct  SiS300_MCLKData_630[] =
+static const struct SiS_MCLKData SiS300_MCLKData_630[] =
 {
        { 0x5a,0x64,0x80, 66},
        { 0xb3,0x45,0x80, 83},
@@ -583,7 +523,7 @@ static const SiS_MCLKDataStruct  SiS300_MCLKData_630[] =
        { 0x37,0x61,0x80,100}
 };
 
-static const SiS_MCLKDataStruct  SiS300_MCLKData_300[] =
+static const struct SiS_MCLKData SiS300_MCLKData_300[] =
 {
        { 0x68,0x43,0x80,125},
        { 0x68,0x43,0x80,125},
@@ -595,7 +535,7 @@ static const SiS_MCLKDataStruct  SiS300_MCLKData_300[] =
        { 0x37,0x61,0x80,100}
 };
 
-static SiS_VCLKDataStruct SiS300_VCLKData[] =
+static struct SiS_VCLKData SiS300_VCLKData[] =
 {
        { 0x1b,0xe1, 25}, /* 0x00 */
        { 0x4e,0xe4, 28}, /* 0x01 */
@@ -669,53 +609,26 @@ static SiS_VCLKDataStruct SiS300_VCLKData[] =
        { 0xe2,0x46,135}, /* 0x45 */  /* 1280x1024-75, better clock for VGA2 */
        { 0x70,0x29, 81}, /* 0x46 */  /* unused */
        {    0,   0,  0}, /* 0x47 custom (will be filled out) */
-       { 0xce,0x25,189}  /* 0x48 */  /* Replacement for index 0x1b for 730 (and 540?) */
+       { 0xce,0x25,189}, /* 0x48 */  /* Replacement for index 0x1b for 730 (and 540?) */
+       { 0x15,0xe1, 20}, /* 0x49 */  /* 640x400@60 (fake, not actually used) */
+       { 0x5f,0xc6, 33}, /* 0x4a */  /* 720x576@60 */
+       { 0x37,0x5a, 10}, /* 0x4b */  /* 320x200@60 (fake, not actually used) */
+       { 0x2b,0xc2, 35}  /* 0x4c */  /* 768@576@60 */
 };
 
-#ifdef LINUX_KERNEL
-static UCHAR SiS300_SR07 = 0x10;
-#endif
-
-static const DRAM4Type SiS300_SR15[8] =
+static const unsigned char SiS300_SR15[4 * 8] =
 {
-       {0x01,0x09,0xa3,0x00},
-       {0x43,0x43,0x43,0x00},
-       {0x1e,0x1e,0x1e,0x00},
-       {0x2a,0x2a,0x2a,0x00},
-       {0x06,0x06,0x06,0x00},
-       {0x00,0x00,0x00,0x00},
-       {0x00,0x00,0x00,0x00},
-       {0x00,0x00,0x00,0x00}
+       0x01,0x09,0xa3,0x00,
+       0x43,0x43,0x43,0x00,
+       0x1e,0x1e,0x1e,0x00,
+       0x2a,0x2a,0x2a,0x00,
+       0x06,0x06,0x06,0x00,
+       0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00
 };
 
-#ifdef LINUX_KERNEL
-static UCHAR SiS300_SR1F = 0x00;
-static UCHAR SiS300_SR21 = 0x16;
-static UCHAR SiS300_SR22 = 0xb2;
-static UCHAR SiS300_SR23 = 0xf6;
-static UCHAR SiS300_SR24 = 0x0d;
-static UCHAR SiS300_SR25[] = {0x0,0x0};
-static UCHAR SiS300_SR31 = 0x00;
-static UCHAR SiS300_SR32 = 0x11;
-static UCHAR SiS300_SR33 = 0x00;
-static UCHAR SiS300_CRT2Data_1_2 = 0x40;
-static UCHAR SiS300_CRT2Data_4_D = 0x00;
-static UCHAR SiS300_CRT2Data_4_E = 0x00;
-static UCHAR SiS300_CRT2Data_4_10 = 0x80;
-
-static const USHORT SiS300_RGBSenseData = 0xd1;
-static const USHORT SiS300_VideoSenseData = 0xb3;
-static const USHORT SiS300_YCSenseData = 0xb9;
-static const USHORT SiS300_RGBSenseData2 = 0x0190;
-static const USHORT SiS300_VideoSenseData2 = 0x0174;
-static const USHORT SiS300_YCSenseData2 = 0x016b;
-
-static const DRAM4Type SiS300_CR40[5];
-
-static UCHAR SiS300_CR49[2];
-#endif
-
-static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
+static const struct SiS_PanelDelayTbl SiS300_PanelDelayTbl[] =
 {
        {{0x05,0xaa}},
        {{0x05,0x14}},
@@ -735,33 +648,11 @@ static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTbl[] =
        {{0x05,0x60}}
 };
 
-#if 0
-static const SiS_PanelDelayTblStruct  SiS300_PanelDelayTblLVDS[] =
-{
-       {{0x05,0xaa}},
-       {{0x05,0x14}},
-       {{0x05,0x36}},
-       {{0x05,0x14}},
-       {{0x05,0x14}},
-       {{0x05,0x14}},
-       {{0x05,0x90}},
-       {{0x05,0x90}},
-       {{0x05,0x14}},
-       {{0x05,0x14}},
-       {{0x05,0x14}},
-       {{0x05,0x14}},  /* 2.07a (JVC): 14,96 */
-       {{0x05,0x28}},  /* 2.04.5c: 20, 80 - Clevo (2.04.2c): 05, 28 */
-       {{0x05,0x14}},
-       {{0x05,0x14}},  /* Some BIOSes: 05, 40 */
-       {{0x05,0x60}}
-};
-#endif
-
 /**************************************************************/
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-static const SiS_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
+static const struct SiS_LCDData SiS300_St2LCD1024x768Data[] =
 {
        {   62,  25, 800, 546,1344, 806},
        {   32,  15, 930, 546,1344, 806},
@@ -772,7 +663,7 @@ static const SiS_LCDDataStruct  SiS300_St2LCD1024x768Data[] =
        {    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
+static const struct SiS_LCDData SiS300_ExtLCD1024x768Data[] =
 {
        {   12,   5, 896, 512,1344, 806},
        {   12,   5, 896, 510,1344, 806},
@@ -789,7 +680,7 @@ static const SiS_LCDDataStruct  SiS300_ExtLCD1024x768Data[] =
        {    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
+static const struct SiS_LCDData SiS300_St2LCD1280x1024Data[] =
 {
        {   22,   5, 800, 510,1650,1088},
        {   22,   5, 800, 510,1650,1088},
@@ -801,7 +692,7 @@ static const SiS_LCDDataStruct  SiS300_St2LCD1280x1024Data[] =
        {    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
+static const struct SiS_LCDData SiS300_ExtLCD1280x1024Data[] =
 {
        {  211,  60,1024, 501,1688,1066},
        {  211,  60,1024, 508,1688,1066},
@@ -813,53 +704,116 @@ static const SiS_LCDDataStruct  SiS300_ExtLCD1280x1024Data[] =
        {    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_1[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_1[] =
 { /* VESA Timing */
-  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
-  {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
-  {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
-  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
-  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
-  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
-  {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
+       {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+       {{0x2c,0x12,0x9a,0xae,0x88,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+       {{0x21,0x12,0xbf,0xe4,0xc0,0x21,0x45,0x09,0x00,0xa9,0x09,0x04}},
+       {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
+       {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+       {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}},
+       {{0x22,0x13,0xfe,0x25,0xff,0x21,0x45,0x0a,0x00,0xa9,0x0d,0x04}}
 };
 
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_2[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_2[] =
 {  /* Non-VESA */
- {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1024x768_3[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_1[] =
-{
-  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
-};
-
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_2[] =
-{
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+       {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+       {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+       {{0x28,0x12,0xa3,0xd0,0xaa,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+       {{0x2c,0x12,0x9a,0xae,0x88,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+       {{0x28,0x13,0xe7,0x0b,0xe8,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+       {{0x38,0x18,0x16,0x00,0x00,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
+       {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}}
 };
 
-static const SiS_Part2PortTblStruct SiS300_CRT2Part2_1280x1024_3[] =
+static const struct SiS_Part2PortTbl SiS300_CRT2Part2_1024x768_3[] =
 {
-  {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
+       {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}
 };
 
 /**************************************************************/
 /* LVDS/Chrontel -------------------------------------------- */
 /**************************************************************/
 
-static const SiS_LVDSDataStruct  SiS300_CHTVUPALData[] =
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_1[]=
+{
+       { 832, 438,1331, 806},
+       { 832, 388,1331, 806},
+       { 832, 438,1331, 806},
+       { 832, 388,1331, 806},
+       { 832, 518,1331, 806},
+       {1050, 638,1344, 806},
+       {1344, 806,1344, 806},
+       {1688,1066,1688,1066},
+       {1688,1066,1688,1066}   /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ R series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1366Data_2[]=
+{
+       {1344, 806,1344, 806},
+       {1344, 806,1344, 806},
+       {1344, 806,1344, 806},
+       {1344, 806,1344, 806},
+       {1344, 806,1344, 806},
+       {1344, 806,1344, 806},
+       {1344, 806,1344, 806},
+       {1688,1066,1688,1066},
+       {1688,1066,1688,1066}   /* 1360x1024 */
+};
+
+/* Custom data for Barco iQ G series */
+static const struct SiS_LVDSData SiS300_LVDSBARCO1024Data_1[]=
+{
+       { 832, 438,1331, 806},
+       { 832, 409,1331, 806},
+       { 832, 438,1331, 806},
+       { 832, 409,1331, 806},
+       { 832, 518,1331, 806},   /* 640x480 */
+       {1050, 638,1344, 806},   /* 800x600 */
+       {1344, 806,1344, 806},   /* 1024x768 */
+};
+
+/* Custom data for 848x480 and 856x480 parallel LVDS panels */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_1[]=
+{
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {1088, 525,1088, 525},  /* 640x480 TODO */
+       {1088, 525,1088, 525},  /* 800x600 TODO */
+       {1088, 525,1088, 525},  /* 1024x768 TODO */
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {1088, 525,1088, 525},  /* 848x480 */
+       {1088, 525,1088, 525},  /* 856x480 */
+       {1088, 525,1088, 525}   /* 1360x768 TODO */
+};
+
+/* Custom data for 848x480 parallel panel */
+static const struct SiS_LVDSData SiS300_LVDS848x480Data_2[]=
+{
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {1088, 525,1088, 525},  /*  640x480 */
+       {1088, 525,1088, 525},  /*  800x600 */
+       {1088, 525,1088, 525},  /* 1024x768 */
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {   0,   0,   0,   0},
+       {1088, 525,1088, 525},  /* 848x480 */
+       {1088, 525,1088, 525},  /* 856x480 */
+       {1088, 525,1088, 525}   /* 1360x768 TODO */
+};
+
+static const struct SiS_LVDSData SiS300_CHTVUPALData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -869,7 +823,7 @@ static const SiS_LVDSDataStruct  SiS300_CHTVUPALData[] =
        { 936, 836, 936, 836}
 };
 
-static const SiS_LVDSDataStruct  SiS300_CHTVOPALData[] =
+static const struct SiS_LVDSData SiS300_CHTVOPALData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -879,7 +833,7 @@ static const SiS_LVDSDataStruct  SiS300_CHTVOPALData[] =
        { 960, 750, 960, 750}
 };
 
-static const SiS_LVDSDataStruct  SiS300_CHTVSOPALData[] =
+static const struct SiS_LVDSData SiS300_CHTVSOPALData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -889,486 +843,8 @@ static const SiS_LVDSDataStruct  SiS300_CHTVSOPALData[] =
        { 944, 625, 944, 625}
 };
 
-
-static const SiS_LVDSDesStruct  SiS300_PanelType00_1[] =
-{
-       { 1059, 626 },   /* 2.08 */
-       { 1059, 624 },
-       { 1059, 626 },
-       { 1059, 624 },
-       { 1059, 624 },
-       {    0, 627 },
-       {    0, 627 },
-       {    0,   0 },
-       {    0,   0 }
-#if 0
-       {0, 626},
-       {0, 624},
-       {0, 626},
-       {0, 624},
-       {0, 624},
-       {0, 627},
-       {0, 627},
-       {0,   0},
-       {0,   0}
-#endif
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType01_1[] =
-{
-       {   0,   0 },  /* 2.08 */
-       {   0,   0 },
-       {   0,   0 },
-       {   0,   0 },
-       {   0,   0 },
-       {   0,   0 },
-       {   0,   0 },
-       {   0,   0 },
-       {   0,   0 }
-#if 0
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-#endif
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType02_1[] =
-{
-       { 1059, 626 },  /* 2.08 */
-       { 1059, 624 },
-       { 1059, 626 },
-       { 1059, 624 },
-       { 1059, 624 },
-       {    0, 627 },
-       {    0, 627 },
-       {    0,   0 },
-       {    0,   0 }
-#if 0
-       {0, 626},
-       {0, 624},
-       {0, 626},
-       {0, 624},
-       {0, 624},
-       {0, 627},
-       {0, 627},
-       {0,   0},
-       {0,   0}
-#endif
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType03_1[] =
-{
-       {   8, 436},
-       {   8, 440},
-       {   8, 436},
-       {   8, 440},
-       {   8, 512},
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType04_1[] =       /* 1280x1024 */
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType05_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType06_1[] =       /* Clevo Trumpion 1024x768 */
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType07_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType08_1[] =
-{
-       {1059, 626},
-       {1059, 624},
-       {1059, 626},
-       {1059, 624},
-       {1059, 624},
-       {   0, 627},
-       {   0, 627},
-       {   0,   0},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType09_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0a_1[] =
-{
-       {1059, 626},
-       {1059, 624},
-       {1059, 626},
-       {1059, 624},
-       {1059, 624},
-       {   0, 627},
-       {   0, 627},
-       {   0,   0},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0b_1[] =
-{
-       {1343,   0},
-       {1343,   0},
-       {1343,   0},
-       {1343,   0},
-       {1343,   0},
-       {1343,   0},
-       {   0, 799},
-       {   0,   0},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0c_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0d_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0e_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},    /* 640x480 */
-       {1343,   0},    /* 800x600 */
-       {   0, 805},    /* 1024x768 */
-       {   0, 794},    /* 1280x1024 */
-       {   0,   0}     /* 1280x960 - not applicable */
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0f_1[] =
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType00_2[] =
-{
-       {976, 527},
-       {976, 502},
-       {976, 527},
-       {976, 502},
-       {976, 567},
-       {  0, 627},
-       {  0, 627},
-       {  0,   0},
-       {  0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType01_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType02_2[] =
-{
-       {976, 527},
-       {976, 502},
-       {976, 527},
-       {976, 502},
-       {976, 567},
-       {  0, 627},
-       {  0, 627},
-       {  0,   0},
-       {  0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType03_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {1152, 622},
-       {1152, 597}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType04_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType05_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType06_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType07_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType08_2[] =
-{
-       {976, 527},
-       {976, 502},
-       {976, 527},
-       {976, 502},
-       {976, 567},
-       {  0, 627},
-       {  0, 627},
-       {  0,   0},
-       {  0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType09_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0a_2[] =
-{
-       {976, 527},
-       {976, 502},
-       {976, 527},
-       {976, 502},
-       {976, 567},
-       {  0, 627},
-       {  0, 627},
-       {  0,   0},
-       {  0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0b_2[] =
-{
-       { 1152, 700},
-       { 1152, 675},
-       { 1152, 700},
-       { 1152, 675},
-       { 1152, 740},
-       { 1232, 799},
-       {    0, 799},
-       {    0,   0},
-       {    0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0c_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0d_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0e_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelType0f_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       {   0, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_1[]=
-{
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0, 805},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS300_PanelTypeNS_2[] =
-{
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0}
-};
-
-/* Custom data for Barco iQ R200/300/400 (BIOS 2.00.07) */
-static const SiS_LVDSDesStruct  SiS300_PanelType04_1a[] =      /* 1280x1024 (1366x1024) */
+/* Custom des data for Barco iQ R200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1a[] =      /* 1280x1024 (1366x1024) */
 {
        {1330, 798},  /* 320x200 */
        {1330, 794},
@@ -1381,7 +857,7 @@ static const SiS_LVDSDesStruct  SiS300_PanelType04_1a[] =  /* 1280x1024 (1366x102
        {   0,   0}   /* 1360x1024          */
 };
 
-static const SiS_LVDSDesStruct  SiS300_PanelType04_2a[] =
+static const struct SiS_LVDSDes SiS300_PanelType04_2a[] =
 {
        {1152, 622},
        {1152, 597},
@@ -1394,8 +870,8 @@ static const SiS_LVDSDesStruct  SiS300_PanelType04_2a[] =
        {   0,   0}
 };
 
-/* Custom data for Barco iQ G200/300/400 (BIOS 2.00.07) */
-static const SiS_LVDSDesStruct  SiS300_PanelType04_1b[] =      /* 1024x768 */
+/* Custom des data for Barco iQ G200/300/400 (BIOS 2.00.07) */
+static const struct SiS_LVDSDes SiS300_PanelType04_1b[] =      /* 1024x768 */
 {
        {1330, 798},  /* 320x200 */
        {1330, 794},
@@ -1406,7 +882,7 @@ static const SiS_LVDSDesStruct  SiS300_PanelType04_1b[] =  /* 1024x768 */
        {   0, 805}   /* 1024x768 / 512x384 */
 };
 
-static const SiS_LVDSDesStruct  SiS300_PanelType04_2b[] =
+static const struct SiS_LVDSDes SiS300_PanelType04_2b[] =
 {
        {1152, 622},
        {1152, 597},
@@ -1419,376 +895,7 @@ static const SiS_LVDSDesStruct  SiS300_PanelType04_2b[] =
 
 /* CRT1 CRTC for slave modes */
 
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1[] =
-{
-       {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
-         0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-         0x00 }},
-       {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-         0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-         0x00 }},
-       {{0x65,0x4f,0x89,0x56,0x83,0xaf,0x1f,
-         0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-         0x00 }},
-       {{0x65,0x4f,0x89,0x56,0x83,0x83,0x1f,
-         0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-         0x00 }},
-       {{0x65,0x4f,0x89,0x56,0x83,0x04,0x3e,
-         0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-         0x00 }},
-       {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-         0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_1_H[] =
-{
-       {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
-         0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
-         0x00 }},
-       {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
-         0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
-         0x00 }},
-       {{0x30,0x27,0x94,0x2c,0x92,0xaf,0x1f,
-         0x90,0x85,0x8f,0xab,0x30,0x00,0x04,
-         0x00 }},
-       {{0x30,0x27,0x94,0x2c,0x92,0x83,0x1f,
-         0x5e,0x83,0x5d,0x79,0x10,0x00,0x04,
-         0x00 }},
-       {{0x30,0x27,0x94,0x2c,0x92,0x04,0x3e,
-         0xe0,0x85,0xdf,0xfb,0x10,0x00,0x04,
-         0x00 }},
-       {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
-         0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1[] =
-{
-       {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-         0x00}},
-       {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
-         0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
-         0x00}},
-       {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-         0x00}},
-       {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
-         0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
-         0x00}},
-       {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
-         0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
-         0x00}},
-       {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
-         0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
-         0x01}},
-       {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-         0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_1_H[] =
-{
-       {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-         0x00 }},
-       {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
-         0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
-         0x00}},
-       {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-         0x00}},
-       {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
-         0x60,0x87,0x5D,0x83,0x10,0x00,0x44,
-         0x00}},
-       {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
-         0xE2,0x89,0xdf,0x05,0x00,0x00,0x44,
-         0x00}},
-       {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
-         0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
-         0x01}},
-       {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-         0x01 }}
-
-#if 0
-       {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-         0x00 }},
-       {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f,
-         0x60,0x87,0x5D,0x83,0x01,0x00,0x44,
-         0x00}},
-       {{0x37,0x27,0x9B,0x2b,0x94,0xc4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-         0x00}},
-       {{0x37,0x27,0x9B,0x2b,0x94,0x97,0x1f,
-         0x60,0x87,0x5D,0x83,0x01,0x00,0x44,
-         0x00}},
-       {{0x37,0x27,0x9B,0x2b,0x94,0x04,0x3e,
-         0xE2,0x89,0xDf,0x05,0x00,0x00,0x44,
-         0x00}},
-       {{0x41,0x31,0x85,0x35,0x1d,0x7c,0xf0,
-         0x5A,0x8F,0x57,0x7D,0x20,0x00,0x55,
-         0x01}},
-       {{0x4f,0x3F,0x93,0x45,0x0D,0x24,0xf5,
-         0x02,0x88,0xFf,0x25,0x10,0x00,0x01,
-         0x01 }}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1[] =
-{
-       {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-         0x00 }},
-       {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
-         0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
-         0x00 }},
-       {{0x63,0x4f,0x87,0x54,0x9f,0xb4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-         0x00 }},
-       {{0x63,0x4f,0x87,0x54,0x9f,0x82,0x1f,
-         0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
-         0x00 }},
-       {{0x63,0x4f,0x87,0x54,0x9f,0x04,0x3e,
-         0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
-         0x00 }},
-       {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
-         0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
-         0x01 }},
-       {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_1_H[] =
-{
-       {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
-         0x00 }},
-       {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f,
-         0x60,0x87,0x5d,0x83,0x10,0x00,0x04,
-         0x00 }},
-       {{0x2f,0x27,0x93,0x2b,0x90,0xb4,0x1f,
-         0x92,0x89,0x8f,0xb5,0x30,0x00,0x04,
-         0x00 }},
-       {{0x2f,0x27,0x93,0x2b,0x90,0x82,0x1f,
-         0x60,0x87,0x5d,0x83,0x10,0x00,0x04,
-         0x00 }},
-       {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
-         0xe2,0x89,0xdf,0x05,0x00,0x00,0x04,
-         0x00 }},
-       {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
-         0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
-         0x01 }},
-       {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2[] =
-{
-       {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-         0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
-         0x00 }},
-       {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-         0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06,
-         0x00 }},
-       {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-         0xf4,0x88,0x8f,0x73,0x20,0x00,0x06,
-         0x00 }},
-       {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-         0xdb,0x8f,0x5d,0x73,0x20,0x00,0x06,
-         0x00 }},
-       {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba,
-         0x1c,0x80,0xdf,0x73,0x00,0x00,0x06,
-         0x00 }},
-       {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-         0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1800x600_2_H[] =
-{
-       {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
-         0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
-         0x00 }},
-       {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
-         0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
-         0x00 }},
-       {{0x3d,0x27,0x81,0x32,0x1a,0x72,0x3e,
-         0xf4,0x88,0x8f,0x73,0x20,0x00,0x05,
-         0x00 }},
-       {{0x3d,0x27,0x81,0x3a,0x1a,0x72,0x3e,
-         0xdb,0x8f,0x5d,0x73,0x20,0x00,0x05,
-         0x00 }},
-       {{0x3d,0x27,0x81,0x32,0x1a,0x72,0xba,
-         0x1c,0x80,0xdf,0x73,0x00,0x00,0x05,
-         0x00 }},
-       {{0x3d,0x31,0x81,0x37,0x1f,0x72,0xf0,
-         0x58,0x8c,0x57,0x73,0x20,0x00,0x05,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2[] =
-{
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
-         0xae,0x84,0x57,0x25,0x30,0x00,0x02,
-         0x01 }},
-       {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11024x768_2_H[] =
-{
-       {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-         0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
-         0xae,0x84,0x57,0x25,0x30,0x00,0x01,
-         0x01 }},
-       {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2[] =
-{
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-         0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
-         0x00 }},
-       {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
-         0xae,0x84,0x57,0x25,0x30,0x00,0x02,
-         0x01 }},
-       {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-         0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT11280x1024_2_H[] =
-{
-       {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
-         0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
-         0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x27,0x93,0x39,0x81,0x24,0xbb,
-         0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
-         0x00 }},
-       {{0x4f,0x31,0x93,0x3e,0x86,0x24,0xf1,
-         0xae,0x84,0x57,0x25,0x30,0x00,0x01,
-         0x01 }},
-       {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-         0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-         0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS300_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
-   0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-
-static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UNTSC[] =
 {
        {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
          0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
@@ -1810,7 +917,7 @@ static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UNTSC[] =
          0x01 }}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1ONTSC[] =
 {
        {{0x64,0x4f,0x88,0x5a,0x9f,0x0b,0x3e,
          0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -1832,7 +939,7 @@ static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1ONTSC[] =
          0x01 }}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1UPAL[] =
 {
        {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
          0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1854,7 +961,7 @@ static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1UPAL[] =
          0x01 }}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1OPAL[] =
 {
        {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
          0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1876,7 +983,7 @@ static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1OPAL[] =
          0x01 }}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
+static const struct SiS_LVDSCRT1Data SiS300_CHTVCRT1SOPAL[] =
 {
        {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
          0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -1898,7 +1005,7 @@ static const SiS_LVDSCRT1DataStruct  SiS300_CHTVCRT1SOPAL[] =
          0x01 }}
 };
 
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UNTSC[] =
 {
        {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
        {{0x4a,0x94,0x00,0x48,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1908,7 +1015,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UNTSC[] =
        {{0x8d,0xc4,0x00,0x3b,0xfb,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 24: 800x600 NTSC 7/10 */
 };
 
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_ONTSC[] =
 {
        {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
        {{0x49,0x94,0x00,0x34,0xfe,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1918,7 +1025,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_ONTSC[] =
        {{0x8c,0xb4,0x00,0x32,0xf9,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 23: 800x600 NTSC 3/4 */
 };
 
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_UPAL[] =
 {
        {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
        {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1929,7 +1036,7 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_UPAL[] =
 
 };
 
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_OPAL[] =
 {
        {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
        {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
@@ -1940,26 +1047,26 @@ static const SiS_CHTVRegDataStruct SiS300_CHTVReg_OPAL[] =
 
 };
 
-static const SiS_CHTVRegDataStruct SiS300_CHTVReg_SOPAL[] =
+static const struct SiS_CHTVRegData SiS300_CHTVReg_SOPAL[] =
 {
        {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 9: 640x400 PAL 1/1 */
        {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
        {{0x41,0x12,0x01,0x50,0x34,0,0,0,0,0,0,0,0,0,0,0}},
        {{0x41,0x12,0x00,0x50,0x00,0,0,0,0,0,0,0,0,0,0,0}},
-       {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* TW: Mode 13: 640x480 PAL 5/4 */
-       {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}}  /* TW: Mode 19: 800x600 PAL 1/1 */
+       {{0x60,0x30,0x00,0x10,0x00,0,0,0,0,0,0,0,0,0,0,0}}, /* Mode 13: 640x480 PAL 5/4 */
+       {{0x81,0x50,0x00,0x1b,0x00,0,0,0,0,0,0,0,0,0,0,0}}  /* Mode 19: 800x600 PAL 1/1 */
 };
 
-static const UCHAR SiS300_CHTVVCLKUNTSC[]  = {0x29,0x29,0x29,0x29,0x2a,0x2e};
+static const unsigned char SiS300_CHTVVCLKUNTSC[]  = { 0x29,0x29,0x29,0x29,0x2a,0x2e };
 
-static const UCHAR SiS300_CHTVVCLKONTSC[]  = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+static const unsigned char SiS300_CHTVVCLKONTSC[]  = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
 
-static const UCHAR SiS300_CHTVVCLKSONTSC[] = {0x2c,0x2c,0x2c,0x2c,0x2d,0x2b};
+static const unsigned char SiS300_CHTVVCLKSONTSC[] = { 0x2c,0x2c,0x2c,0x2c,0x2d,0x2b };
 
-static const UCHAR SiS300_CHTVVCLKUPAL[]   = {0x2f,0x2f,0x2f,0x2f,0x2f,0x31};
+static const unsigned char SiS300_CHTVVCLKUPAL[]   = { 0x2f,0x2f,0x2f,0x2f,0x2f,0x31 };
 
-static const UCHAR SiS300_CHTVVCLKOPAL[]   = {0x2f,0x2f,0x2f,0x2f,0x30,0x32};
+static const unsigned char SiS300_CHTVVCLKOPAL[]   = { 0x2f,0x2f,0x2f,0x2f,0x30,0x32 };
 
-static const UCHAR SiS300_CHTVVCLKSOPAL[]  = {0x2f,0x2f,0x2f,0x2f,0x36,0x29};
+static const unsigned char SiS300_CHTVVCLKSOPAL[]  = { 0x2f,0x2f,0x2f,0x2f,0x36,0x29 };
 
 
index 2c71d048f7c40374b1d63ea5d79caccdc7b35e61..54fcbbf4ef635fb8c72e588c010ba4577d6e7118 100644 (file)
@@ -1,9 +1,9 @@
 /* $XFree86$ */
 /* $XdotOrg$ */
 /*
- * Register settings for SiS 315/330 series
+ * Register settings for SiS 315/330/340 series
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-static const SiS_StStruct SiS310_SModeIDTable[]=
-{
-       {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00, 0x40},
-       {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00, 0x40},
-       {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01, 0x40},
-       {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02, 0x40},
-       {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02, 0x40},
-       {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03, 0x40},
-       {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04, 0x40},
-       {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05, 0x40},
-       {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03, 0x40},
-       {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03, 0x40},
-       {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04, 0x40},
-       {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05, 0x40},
-       {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05, 0x40},
-       {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05, 0x40},
-       {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05, 0x40},
-       {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05, 0x40},
-       {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04, 0x40},
-       {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05, 0x40},
-       {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05, 0x40},
-       {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00, 0x40}
-};
-
-static const SiS_ExtStruct  SiS310_EModeIDTable[]=
+static const struct SiS_Ext SiS310_EModeIDTable[] =
 {
        {0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
        {0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
-        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+       {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
        {0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
-        {0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+       {0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
        {0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
        {0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
        {0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
@@ -103,10 +79,10 @@ static const SiS_ExtStruct  SiS310_EModeIDTable[]=
        {0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
        {0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8  */
        {0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8  */
-       {0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
+       {0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
        {0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
        {0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
-       {0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+       {0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
        {0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8  */
        {0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8  fstn */
        {0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
@@ -139,406 +115,335 @@ static const SiS_ExtStruct  SiS310_EModeIDTable[]=
        {0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
        {0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
        {0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
-       {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */
-       {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */
-       {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/
-       {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */
-       {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
-       {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
-       {0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x46,-1}, /* 848x480 */
-       {0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x46,-1},
-       {0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x46,-1},
-       {0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x48,-1}, /* 856x480 */
-       {0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x48,-1},
-       {0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x48,-1},
-       {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1}, /* 1360x768 */
-       {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1},
-       {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4a,-1},
+       {0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x8 */
+       {0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x16 */
+       {0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x43, 9}, /* 1400x1050x32*/
+       {0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1}, /* 1152x864 */
+       {0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+       {0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x45,-1},
+       {0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1}, /* 848x480 */
+       {0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1},
+       {0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x48,-1},
+       {0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1}, /* 856x480 */
+       {0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1},
+       {0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x4a,-1},
+       {0x48,0x6a3b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1}, /* 1360x768 */
+       {0x4b,0x6a7d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
+       {0x4e,0x6aff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x4c,-1},
        {0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
        {0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
        {0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
-       {0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4b,-1}, /* 768x576 */
-       {0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4b,-1},
-       {0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4b,-1},
-       {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7}, /* 1280x800 */
-       {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7},
-       {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4c, 7},
-       {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9}, /* 1680x1050 */
-       {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9},
-       {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4d, 9},
-       {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1}, /* 1920x1080(i) */
-       {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1},
-       {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x4e,-1},
-       {0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x4f,-1}, /* 960x540 */
-       {0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x4f,-1},
-       {0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x4f,-1},
-       {0x20,0x6a1b,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x50,-1}, /* 960x600 */
-       {0x21,0x6a3d,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x50,-1},
-       {0x22,0x6a7f,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x50,-1},
+       {0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1}, /* 768x576 */
+       {0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1},
+       {0x61,0x6a3f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4d,-1},
+       {0x14,0x0e3b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7}, /* 1280x800 */
+       {0x15,0x0e7d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+       {0x16,0x0eff,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4e, 7},
+       {0x17,0x0e3b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9}, /* 1680x1050 */
+       {0x18,0x0e7d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+       {0x19,0x0eff,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x51, 9},
+       {0x2c,0x267b,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1}, /* 1920x1080(i) */
+       {0x2d,0x26fd,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+       {0x73,0x27ff,0x0000,SIS_RI_1920x1080,0x00,0x00,0x00,0x00,0x52,-1},
+       {0x1d,0x6a1b,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1}, /* 960x540 */
+       {0x1e,0x6a3d,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1},
+       {0x1f,0x6a7f,0x0000,SIS_RI_960x540,  0x00,0x00,0x00,0x00,0x53,-1},
+       {0x20,0x6a1b,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1}, /* 960x600 */
+       {0x21,0x6a3d,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1},
+       {0x22,0x6a7f,0x0000,SIS_RI_960x600,  0x00,0x00,0x00,0x00,0x54,-1},
+       {0x1a,0x0e3b,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8}, /* 1280x854 */
+       {0x1b,0x0e7d,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
+       {0x1c,0x0eff,0x0000,SIS_RI_1280x854, 0x00,0x00,0x00,0x00,0x55, 8},
        {0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
 };
 
-static const SiS_Ext2Struct SiS310_RefIndex[]=
-{
-       {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x0 */
-       {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40}, /* 0x1 */
-       {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40}, /* 0x2 */
-       {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40}, /* 0x3 */
-       {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x4 */
-       {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40}, /* 0x5 */
-       {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x6 */
-       {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20}, /* 0x7 */
-       {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x8 */
-       {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40}, /* 0x9 */
-       {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40}, /* 0xa */
-       {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40}, /* 0xb */
-       {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xc */
-       {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xd */
-       {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
-       {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
-       {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
-       {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */
-       {0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */
-       {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
-       {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
-       {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
-       {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20}, /* 0x16 */
-       {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20}, /* 0x17 */
-       {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x18 */
-       {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10}, /* 0x19 */
-       {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30}, /* 0x1a */
-       {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00}, /* 0x1b */
-       {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1c */
-       {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00}, /* 0x1d */
-       {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00}, /* 0x1e */
-       {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x1f */
-       {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x20 */
-       {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x21 */
-       {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x22 */
-       {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x23 */
-       {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00}, /* 0x24 */
-       {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30}, /* 0x25 */
-       {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30}, /* 0x26 */
-       {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30}, /* 0x27 */
-       {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30}, /* 0x28 */
-       {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x29 */
-       {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2a */
-       {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2b */
-       {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2c */
-       {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2d */
-       {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00}, /* 0x2e */
-       {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x2f */
-       {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x30 */
-       {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
-       {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
-       {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
-       {0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */
-       {0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */
-       {0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */
-       {0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */
-       {0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */
-       {0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */
-       {0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
-       {0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
-       {0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
-       {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30}, /* 0x3d */
-       {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20}, /* 0x3e */
-       {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30}, /* 0x3f */    /* FSTN 320x240 */
-        {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */    /* 0x5b was 0x12 */
-       {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
-       {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
-       {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-60Hz  */
-       {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-75Hz  */
-       {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x45 1152x864-85Hz  */
-       {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-38Hzi  */
-       {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x47 848x480-60Hz   */
-       {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-38Hzi  */
-       {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x49 856x480-60Hz   */
-       {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x4a 1360x768-60Hz  */
-       {0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4b 768x576-56Hz   */
-       {0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4c 1280x800-60Hz  */
-       {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4d 1680x1050-60Hz */
-       {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30}, /* 0x4e 1920x1080 60Hzi */
-       {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30}, /* 0x4f 960x540 60Hz */
-       {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30}, /* 0x50 960x600 60Hz */
-       {0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0}
-};
-
-#ifdef LINUX_XF86
-static const struct {
-       UCHAR  Ext_ModeID;     /* ModeID in new ROM */
-       UCHAR  Ext_MyModeID;   /* corresponding ModeID in my tables (0 = identical) */
-       USHORT Ext_VESAID;     /* corresponding VESA ID in new ROM */
-} SiS_EModeIDTable661[] = {
-        { 0x6a, 0x00, 0x0102 },
-       { 0x1d, 0x20, 0x0000 },
-       { 0x1e, 0x21, 0x0000 },
-       { 0x1f, 0x22, 0x0000 },
-       { 0x20, 0x29, 0x0000 },
-       { 0x21, 0x2a, 0x0000 },
-       { 0x22, 0x2b, 0x0000 },
-       { 0x23, 0x00, 0x011c },
-       { 0x24, 0x00, 0x011d },
-       { 0x25, 0x00, 0x011e },
-       { 0x26, 0x00, 0x011f },
-       { 0x27, 0x00, 0x0120 },
-       { 0x28, 0x00, 0x0121 },
-       { 0x2a, 0x14, 0x013d },
-       { 0x2b, 0x15, 0x013e },
-       { 0x2c, 0x16, 0x013f },
-       { 0x2e, 0x00, 0x0101 },
-       { 0x2f, 0x00, 0x0100 },
-       { 0x30, 0x00, 0x0103 },
-       { 0x37, 0x00, 0x0104 },
-       { 0x38, 0x00, 0x0105 },
-       { 0x3a, 0x00, 0x0107 },
-       { 0x3c, 0x00, 0x0125 },
-       { 0x3d, 0x00, 0x0126 },
-       { 0x40, 0x00, 0x010d },
-       { 0x41, 0x00, 0x010e },
-       { 0x43, 0x00, 0x0110 },
-       { 0x44, 0x00, 0x0111 },
-       { 0x46, 0x00, 0x0113 },
-       { 0x47, 0x00, 0x0114 },
-       { 0x49, 0x00, 0x0116 },
-       { 0x4a, 0x00, 0x0117 },
-       { 0x4c, 0x00, 0x0119 },
-       { 0x4d, 0x00, 0x011a },
-       { 0x50, 0x00, 0x0127 },
-       { 0x51, 0x00, 0x0128 },
-       { 0x52, 0x00, 0x0129 },
-       { 0x56, 0x00, 0x012a },
-       { 0x57, 0x00, 0x012b },
-       { 0x58, 0x00, 0x012c },
-       { 0x59, 0x00, 0x012d },
-       { 0x5a, 0x17, 0x012e },
-       { 0x5b, 0x18, 0x012f },
-       { 0x5c, 0x19, 0x0130 },
-       { 0x5d, 0x00, 0x0131 },
-       { 0x62, 0x00, 0x0112 },
-       { 0x63, 0x00, 0x0115 },
-       { 0x64, 0x00, 0x0118 },
-       { 0x65, 0x00, 0x011b },
-       { 0x66, 0x00, 0x0132 },
-       { 0x75, 0x00, 0x013a },
-       { 0x78, 0x00, 0x013b },
-       { 0x79, 0x00, 0x013c },
-       { 0x7b, 0x7c, 0x0136 },
-       { 0x7c, 0x7d, 0x0137 },
-       { 0x7d, 0x7e, 0x0138 },
-       { 0xff, 0xff, 0xffff }
-};
-#endif
-
-static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
+static const struct SiS_Ext2 SiS310_RefIndex[] =
+{
+       {0x085f,0x0d,0x03,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x0 */
+       {0x0067,0x0e,0x04,0x05,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1 */
+       {0x0067,0x0f,0x08,0x48,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2 */
+       {0x0067,0x10,0x07,0x8b,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3 */
+       {0x0047,0x11,0x0a,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4 */
+       {0x0047,0x12,0x0d,0x00,0x05,0x6a, 800, 600, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x5 */
+       {0x0047,0x13,0x13,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x6 */
+       {0x0107,0x14,0x1c,0x00,0x05,0x6a, 800, 600, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x7 */
+       {0xc85f,0x05,0x00,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x8 */
+       {0xc067,0x06,0x02,0x04,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x9 */
+       {0xc067,0x07,0x02,0x47,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xa */
+       {0xc067,0x08,0x03,0x8a,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xb */
+       {0xc047,0x09,0x05,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xc */
+       {0xc047,0x0a,0x09,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xd */
+       {0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xe */
+       {0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0xf */
+       {0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30, 0x55, 0x6e, 0x00, 0x00, 0x00, 0x00}, /* 0x10 */
+       {0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x11 */
+       {0x006f,0x3d,0x6f,0x06,0x14,0x32, 720, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x12 (6f was 03) */
+       {0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x13 */
+       {0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x14 */
+       {0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x15 */
+       {0x0067,0x18,0x11,0x00,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x16 */
+       {0x0047,0x19,0x16,0x8c,0x06,0x37,1024, 768, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x17 */
+       {0x0107,0x1a,0x1b,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x18 */
+       {0x0107,0x1b,0x1f,0x00,0x06,0x37,1024, 768, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x19 */
+       {0x0087,0x1c,0x11,0x00,0x07,0x3a,1280,1024, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1a */
+       {0x0137,0x1d,0x19,0x07,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1b */
+       {0x0107,0x1e,0x1e,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1c */
+       {0x0207,0x1f,0x20,0x00,0x07,0x3a,1280,1024, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1d */
+       {0x0227,0x20,0x21,0x09,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1e */
+       {0x0407,0x21,0x22,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x1f */
+       {0x0407,0x22,0x23,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x20 */
+       {0x0407,0x23,0x25,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x21 */
+       {0x0007,0x24,0x26,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x22 */
+       {0x0007,0x25,0x2c,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x23 */
+       {0x0007,0x26,0x34,0x00,0x09,0x3c,1600,1200, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x24 */
+       {0x407f,0x00,0x00,0x00,0x00,0x40, 320, 200, 0x30, 0x56, 0x4e, 0x00, 0x00, 0x00, 0x00}, /* 0x25 */
+       {0xc07f,0x01,0x00,0x04,0x04,0x50, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x26 */
+       {0x007f,0x02,0x04,0x05,0x05,0x51, 400, 300, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x27 */
+       {0xc077,0x03,0x0b,0x06,0x06,0x52, 512, 384, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x28 */
+       {0x8007,0x27,0x27,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x29 */
+       {0x4007,0x28,0x29,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2a */
+       {0x4007,0x29,0x2e,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2b */
+       {0x4007,0x2a,0x30,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2c */
+       {0x4007,0x2b,0x35,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2d */
+       {0x4005,0x2c,0x39,0x00,0x00,0x68,1920,1440, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2e */
+       {0x4007,0x2d,0x2b,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x2f */
+       {0x4007,0x2e,0x31,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x30 */
+       {0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x31 */
+       {0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x32 */
+       {0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x33 */
+       {0x2077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x32, 0x40, 0x5e, 0x73}, /* 0x34 */
+       {0x2047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x33, 0x07, 0xff, 0xff}, /* 0x35 */
+       {0x2047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30, 0x00, 0x00, 0x34, 0x0a, 0xff, 0xff}, /* 0x36 */
+       {0x2077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x35, 0x0b, 0x5f, 0x74}, /* 0x37 */
+       {0x2047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x36, 0x11, 0xff, 0xff}, /* 0x38 */
+       {0x2047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30, 0x00, 0x00, 0x37, 0x16, 0xff, 0xff}, /* 0x39 */
+       {0x3137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x38, 0x19, 0x60, 0x75}, /* 0x3a */
+       {0x3107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x39, 0x1e, 0xff, 0xff}, /* 0x3b */
+       {0x3307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30, 0x00, 0x00, 0x3a, 0x20, 0xff, 0xff}, /* 0x3c */
+       {0x0127,0x3b,0x19,0x08,0x0a,0x7c,1280, 960, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3d */
+       {0x0227,0x4c,0x59,0x08,0x0a,0x7c,1280, 960, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3e */
+       {0xc07f,0x4e,0x00,0x06,0x04,0x5a, 320, 240, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x3f */    /* FSTN 320x240 */
+       {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x58, 0x19, 0x42, 0x5b}, /* 0x40 */    /* 0x5b was 0x12 */
+       {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x59, 0x1e, 0xff, 0xff}, /* 0x41 */
+       {0x2077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30, 0x00, 0x00, 0x5a, 0x20, 0xff, 0xff}, /* 0x42 */
+       {0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x43 */
+       {0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x44 1400x1050-75Hz */
+       {0x0127,0x54,0x6d,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x45 1152x864-60Hz  */
+       {0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x46 1152x864-75Hz  */
+       {0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x47 1152x864-85Hz  */
+       {0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x48 848x480-38Hzi  */
+       {0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x49 848x480-60Hz   */
+       {0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4a 856x480-38Hzi  */
+       {0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4b 856x480-60Hz   */
+       {0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4c 1360x768-60Hz  */
+       {0x006f,0x4d,0x71,0x06,0x15,0x5f, 768, 576, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x4d 768x576-56Hz   */
+       {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5b, 0x19, 0x4f, 0x5c}, /* 0x4e 1280x800-60Hz  */
+       {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5c, 0x1e, 0xff, 0xff}, /* 0x4f 1280x800-75Hz  */
+       {0x2067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30, 0x00, 0x00, 0x5d, 0x20, 0xff, 0xff}, /* 0x50 1280x800-85Hz  */
+       {0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x51 1680x1050-60Hz */
+       {0x0087,0x51,0x69,0x00,0x00,0x2c,1920,1080, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x52 1920x1080 60Hzi */
+       {0x0067,0x52,0x6a,0x00,0x1c,0x1d, 960, 540, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x53 960x540 60Hz */
+       {0x0077,0x53,0x6b,0x0b,0x1d,0x20, 960, 600, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0x54 960x600 60Hz */
+       {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x62, 0x19, 0x61, 0x76}, /* 0x55 1280x854-60Hz  */
+       {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x63, 0x1e, 0xff, 0xff}, /* 0x56 1280x854-75Hz  */
+       {0x2067,0x61,0x76,0x0d,0x22,0x1a,1280, 854, 0x30, 0x00, 0x00, 0x64, 0x20, 0xff, 0xff}, /* 0x57 1280x854-85Hz  */
+       {0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+
+static const struct SiS_CRT1Table SiS310_CRT1Table[] =
 {
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0xbf,0x1f,
    0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x00,
-   0x00}}, /* 0x0 */
+   0x00}},  /* 0x0 */
  {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e,
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}, /* 0x1 */
+   0x00}},  /* 0x1 */
  {{0x3d,0x31,0x31,0x81,0x37,0x1f,0x72,0xf0,
    0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x05,
-   0x01}}, /* 0x2 */
+   0x01}},  /* 0x2 */
  {{0x4f,0x3f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
    0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x01,
-   0x01}}, /* 0x3 */
+   0x01}},  /* 0x3 */
  {{0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,
    0x9c,0x8e,0x8f,0x96,0xb9,0x30,0x00,0x05,
-   0x00}}, /* 0x4 */
-#if 0
- {{0x5f,0x4f,0x50,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
-   0x00}}, /* 0x5 */
-#endif
- {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* 0x05 - corrected 640x480-60 */
+   0x00}},  /* 0x4 */
+ {{0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,    /* corrected 640x480-60 */
    0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
-   0x00}},
-#if 0   
- {{0x63,0x4f,0x50,0x86,0x56,0x9b,0x06,0x3e,
-   0xe8,0x8b,0xdf,0xe7,0xff,0x10,0x00,0x01,
-   0x00}}, /* 0x6 */
-#endif
- {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* 0x06 - corrected 640x480-72 */
+   0x00}},  /* 0x5 */
+ {{0x63,0x4f,0x4f,0x87,0x56,0x9b,0x06,0x3e,    /* corrected 640x480-72 */
    0xe8,0x8a,0xdf,0xe7,0x07,0x00,0x00,0x01,
-   0x00}},
+   0x00}},  /* 0x6 */
  {{0x64,0x4f,0x4f,0x88,0x55,0x9d,0xf2,0x1f,
    0xe0,0x83,0xdf,0xdf,0xf3,0x10,0x00,0x01,
-   0x00}}, /* 0x7 */
+   0x00}},  /* 0x7 */
  {{0x63,0x4f,0x4f,0x87,0x5a,0x81,0xfb,0x1f,
    0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,
-   0x00}}, /* 0x8 */
+   0x00}},  /* 0x8 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0xfb,0x1f,
    0xe0,0x83,0xdf,0xdf,0xfc,0x10,0x00,0x05,  /* Corrected VBE */
-   0x61}}, /* 0x9 */
+   0x61}},  /* 0x9 */
  {{0x65,0x4f,0x4f,0x89,0x58,0x80,0x01,0x3e,
    0xe0,0x83,0xdf,0xdf,0x02,0x00,0x00,0x05,
-   0x61}}, /* 0xa */
+   0x61}},  /* 0xa */
  {{0x67,0x4f,0x4f,0x8b,0x58,0x81,0x0d,0x3e,
    0xe0,0x83,0xdf,0xdf,0x0e,0x00,0x00,0x05,  /* Corrected VBE */
-   0x61}}, /* 0xb */
+   0x61}},  /* 0xb */
  {{0x65,0x4f,0x4f,0x89,0x57,0x9f,0xfb,0x1f,
    0xe6,0x8a,0xdf,0xdf,0xfc,0x10,0x00,0x01,  /* Corrected VDE, VBE */
-   0x00}}, /* 0xc */
+   0x00}},  /* 0xc */
  {{0x7b,0x63,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
    0x58,0x8a,0x57,0x57,0x70,0x20,0x00,0x05,
-   0x01}}, /* 0xd */
+   0x01}},  /* 0xd */
  {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xf0,
    0x58,0x8c,0x57,0x57,0x73,0x20,0x00,0x06,
-   0x01}}, /* 0xe */
+   0x01}},  /* 0xe */
  {{0x7d,0x63,0x63,0x81,0x6e,0x1d,0x98,0xf0,
    0x7c,0x82,0x57,0x57,0x99,0x00,0x00,0x06,
-   0x01}}, /* 0xf */
+   0x01}},  /* 0xf */
  {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xf0,
    0x58,0x8b,0x57,0x57,0x70,0x20,0x00,0x06,
-   0x01}}, /* 0x10 */
+   0x01}},  /* 0x10 */
  {{0x7e,0x63,0x63,0x82,0x6b,0x13,0x75,0xf0,
    0x58,0x8b,0x57,0x57,0x76,0x20,0x00,0x06,
-   0x01}}, /* 0x11 */
+   0x01}},  /* 0x11 */
  {{0x81,0x63,0x63,0x85,0x6d,0x18,0x7a,0xf0,
    0x58,0x8b,0x57,0x57,0x7b,0x20,0x00,0x06,
-   0x61}}, /* 0x12 */
+   0x61}},  /* 0x12 */
  {{0x83,0x63,0x63,0x87,0x6e,0x19,0x81,0xf0,
    0x58,0x8b,0x57,0x57,0x82,0x20,0x00,0x06,
-   0x61}}, /* 0x13 */
+   0x61}},  /* 0x13 */
  {{0x85,0x63,0x63,0x89,0x6f,0x1a,0x91,0xf0,
    0x58,0x8b,0x57,0x57,0x92,0x20,0x00,0x06,
-   0x61}}, /* 0x14 */
+   0x61}},  /* 0x14 */
  {{0x99,0x7f,0x7f,0x9d,0x84,0x1a,0x96,0x1f,
    0x7f,0x83,0x7f,0x7f,0x97,0x10,0x00,0x02,
-   0x00}}, /* 0x15 */
+   0x00}},  /* 0x15 */
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf5,
    0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}, /* 0x16 */
+   0x01}},  /* 0x16 */
  {{0xa1,0x7f,0x7f,0x85,0x86,0x97,0x24,0xf5,
    0x02,0x88,0xff,0xff,0x25,0x10,0x00,0x02,
-   0x01}}, /* 0x17 */
+   0x01}},  /* 0x17 */
  {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf5,
    0x00,0x83,0xff,0xff,0x1f,0x10,0x00,0x02,
-   0x01}}, /* 0x18 */
+   0x01}},  /* 0x18 */
  {{0xa7,0x7f,0x7f,0x8b,0x89,0x95,0x26,0xf5,
    0x00,0x83,0xff,0xff,0x27,0x10,0x00,0x02,
-   0x01}}, /* 0x19 */
+   0x01}},  /* 0x19 */
  {{0xa9,0x7f,0x7f,0x8d,0x8c,0x9a,0x2c,0xf5,
    0x00,0x83,0xff,0xff,0x2d,0x14,0x00,0x02,
-   0x62}}, /* 0x1a */
+   0x62}},  /* 0x1a */
  {{0xab,0x7f,0x7f,0x8f,0x8d,0x9b,0x35,0xf5,
    0x00,0x83,0xff,0xff,0x36,0x14,0x00,0x02,
-   0x62}}, /* 0x1b */
+   0x62}},  /* 0x1b */
  {{0xcf,0x9f,0x9f,0x93,0xb2,0x01,0x14,0xba,
    0x00,0x83,0xff,0xff,0x15,0x00,0x00,0x03,
-   0x00}}, /* 0x1c */
+   0x00}},  /* 0x1c */
  {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0x5a,
    0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
-   0x01}}, /* 0x1d */
+   0x01}},  /* 0x1d */
  {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0x5a,
    0x00,0x83,0xff,0xff,0x29,0x09,0x00,0x07,
-   0x01}}, /* 0x1e */
+   0x01}},  /* 0x1e */
  {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0x5a,
    0x00,0x83,0xff,0xff,0x2f,0x09,0x00,0x07,
-   0x01}}, /* 0x1f */
+   0x01}},  /* 0x1f */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x20 */
+   0x00}},  /* 0x20 */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x21 @ 4084 */
+   0x00}},  /* 0x21 */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x22 */
+   0x00}},  /* 0x22 */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x23 */
+   0x00}},  /* 0x23 */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x24 */
+   0x00}},  /* 0x24 */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x25 */
+   0x00}},  /* 0x25 */
  {{0x09,0xc7,0xc7,0x8d,0xd3,0x0b,0xe0,0x10,
    0xb0,0x83,0xaf,0xaf,0xe1,0x2f,0x01,0x04,
-   0x00}}, /* 0x26 */
+   0x00}},  /* 0x26 */
  {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
    0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}}, /* 0x27 */
+   0x00}},  /* 0x27 */
  {{0x43,0xef,0xef,0x87,0x06,0x00,0xd4,0x1f,
    0xa0,0x83,0x9f,0x9f,0xd5,0x1f,0x41,0x05,
-   0x63}}, /* 0x28 */
+   0x63}},  /* 0x28 */
  {{0x45,0xef,0xef,0x89,0x07,0x01,0xd9,0x1f,
    0xa0,0x83,0x9f,0x9f,0xda,0x1f,0x41,0x05,
-   0x63}}, /* 0x29 */
+   0x63}},  /* 0x29 */
  {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
    0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}}, /* 0x2a */
+   0x00}},  /* 0x2a */
  {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
    0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}}, /* 0x2b */
+   0x00}},  /* 0x2b */
  {{0x40,0xef,0xef,0x84,0x03,0x1d,0xda,0x1f,
    0xa0,0x83,0x9f,0x9f,0xdb,0x1f,0x41,0x01,
-   0x00}}, /* 0x2c */
+   0x00}},  /* 0x2c */
  {{0x59,0xff,0xff,0x9d,0x17,0x13,0x33,0xba,
    0x00,0x83,0xff,0xff,0x34,0x0f,0x41,0x05,
-   0x44}}, /* 0x2d */
+   0x44}},  /* 0x2d */
  {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x38,0xba,
    0x00,0x83,0xff,0xff,0x39,0x0f,0x41,0x05,
-   0x44}}, /* 0x2e */
+   0x44}},  /* 0x2e */
  {{0x5b,0xff,0xff,0x9f,0x18,0x14,0x3d,0xba,
    0x00,0x83,0xff,0xff,0x3e,0x0f,0x41,0x05,
-   0x44}}, /* 0x2f */
+   0x44}},  /* 0x2f */
  {{0x5d,0xff,0xff,0x81,0x19,0x95,0x41,0xba,
    0x00,0x84,0xff,0xff,0x42,0x0f,0x41,0x05,
-   0x44}}, /* 0x30 */
+   0x44}},  /* 0x30 */
  {{0x55,0xff,0xff,0x99,0x0d,0x0c,0x3e,0xba,
    0x00,0x84,0xff,0xff,0x3f,0x0f,0x41,0x05,
-   0x00}}, /* 0x31 */
+   0x00}},  /* 0x31 */
  {{0x7f,0x63,0x63,0x83,0x6c,0x1c,0x72,0xba,
    0x27,0x8b,0xdf,0xdf,0x73,0x00,0x00,0x06,
-   0x01}}, /* 0x32 */
+   0x01}},  /* 0x32 */
  {{0x7f,0x63,0x63,0x83,0x69,0x13,0x6f,0xba,
    0x26,0x89,0xdf,0xdf,0x6f,0x00,0x00,0x06,
-   0x01}}, /* 0x33 */
+   0x01}},  /* 0x33 */
  {{0x7f,0x63,0x63,0x82,0x6b,0x13,0x75,0xba,
    0x29,0x8c,0xdf,0xdf,0x75,0x00,0x00,0x06,
-   0x01}}, /* 0x34 */
+   0x01}},  /* 0x34 */
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x24,0xf1,
    0xaf,0x85,0x3f,0x3f,0x25,0x30,0x00,0x02,
-   0x01}}, /* 0x35 */
+   0x01}},  /* 0x35 */
  {{0x9f,0x7f,0x7f,0x83,0x85,0x91,0x1e,0xf1,
    0xad,0x81,0x3f,0x3f,0x1f,0x30,0x00,0x02,
-   0x01}}, /* 0x36 */
+   0x01}},  /* 0x36 */
  {{0xa7,0x7f,0x7f,0x88,0x89,0x95,0x26,0xf1,   /* 95 was 15 - illegal HBE! */
    0xb1,0x85,0x3f,0x3f,0x27,0x30,0x00,0x02,
-   0x01}}, /* 0x37 */
+   0x01}},  /* 0x37 */
  {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xc4,
    0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-   0x01}}, /* 0x38 */
+   0x01}},  /* 0x38 */
  {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xd4,
    0x7a,0x8e,0xcf,0xcf,0x29,0x21,0x00,0x07,
-   0x01}}, /* 0x39 */
+   0x01}},  /* 0x39 */
  {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xd4,
    0x7d,0x81,0xcf,0xcf,0x2f,0x21,0x00,0x07,
-   0x01}}, /* 0x3a */
-#if 0   
- {{0xdc,0x9f,0x9f,0x00,0xab,0x19,0xe6,0xef,    /* 1280x960 - invalid */
-   0xc0,0xc3,0xbf,0xbf,0xe7,0x10,0x00,0x07,
-   0x01}}, /* 0x3b */
-#endif  
+   0x01}},  /* 0x3a */
  {{0xdc,0x9f,0x9f,0x80,0xaf,0x9d,0xe6,0xff,    /* 1280x960-60 - corrected */
    0xc0,0x83,0xbf,0xbf,0xe7,0x10,0x00,0x07,
-   0x01}}, /* 0x3b */ 
+   0x01}},  /* 0x3b */
  {{0x6b,0x59,0x59,0x8f,0x5e,0x8c,0x0b,0x3e,
    0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x05,
-   0x00}}, /* 0x3c */
- {{0x7b,0x59,0x63,0x9f,0x6a,0x93,0x6f,0xf0,
-   0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
-   0x01}}, /* 0x3d */
+   0x00}},  /* 0x3c */
+ {{0x6d,0x59,0x59,0x91,0x60,0x89,0x53,0xf0,    /* 720x576, corrected to 60Hz */
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}},  /* 0x3d */
  {{0x86,0x6a,0x6a,0x8a,0x74,0x06,0x8c,0x15,
    0x4f,0x83,0xef,0xef,0x8d,0x30,0x00,0x02,
-   0x00}}, /* 0x3e */
+   0x00}},  /* 0x3e */
  {{0x81,0x6a,0x6a,0x85,0x70,0x00,0x0f,0x3e,
    0xeb,0x8e,0xdf,0xdf,0x10,0x00,0x00,0x02,
-   0x00}}, /* 0x3f */
+   0x00}},  /* 0x3f */
  {{0xa3,0x7f,0x7f,0x87,0x86,0x97,0x1e,0xf1,
    0xae,0x85,0x57,0x57,0x1f,0x30,0x00,0x02,
    0x01}},  /* 0x40 */
@@ -578,11 +483,11 @@ static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
  {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0xf1,0xff, /* 1280x960-85 */
    0xc0,0x83,0xbf,0xbf,0xf2,0x10,0x00,0x07,
    0x01}},  /* 0x4c */
- {{0x7b,0x5f,0x63,0x9f,0x6a,0x93,0x6f,0xf0, /* 768x576 */
-   0x58,0x8a,0x3f,0x57,0x70,0x20,0x00,0x05,
-   0x01}},  /* 0x4d */
- {{0x2d,0x27,0x28,0x90,0x2c,0x80,0x0b,0x3e, /* FSTN 320x480, TEMP - possibly invalid */
-   0xe9,0x8b,0xdf,0xe7,0x04,0x00,0x00,0x00,
+ {{0x75,0x5f,0x5f,0x99,0x66,0x90,0x53,0xf0, /* 768x576, corrected to 60Hz */
+   0x41,0x84,0x3f,0x3f,0x54,0x00,0x00,0x05,
+   0x41}},  /* 0x4d */
+ {{0x5f,0x27,0x4f,0x83,0x55,0x81,0x0b,0x3e, /* FSTN 320x240 (working) */
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
    0x00}},  /* 0x4e */
  {{0xcd,0x9f,0x9f,0x91,0xab,0x1c,0x3a,0xff, /* 1280x800-60 */
    0x20,0x83,0x1f,0x1f,0x3b,0x10,0x00,0x07,
@@ -601,10 +506,58 @@ static const SiS_CRT1TableStruct SiS310_CRT1Table[]=
    0x01}},  /* 0x53 */
  {{0xcd,0x8f,0x8f,0x91,0x9b,0x1b,0x7a,0xff, /* 1152x864-60 */
    0x64,0x8c,0x5f,0x62,0x7b,0x10,0x00,0x07,
-   0x41}}   /* 0x54 */
-};
-
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
+   0x41}},  /* 0x54 */
+ {{0x5c,0x4f,0x4f,0x80,0x57,0x80,0xa3,0x1f, /* fake 640x400@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa4,0x30,0x00,0x05,
+   0x40}},  /* 0x55 */
+ {{0x2c,0x27,0x27,0x90,0x2d,0x92,0xa4,0x1f, /* fake 320x200@60Hz (for LCD and TV, not actually used) */
+   0x98,0x8c,0x8f,0x96,0xa5,0x30,0x00,0x04,
+   0x00}},  /* 0x56 */
+ {{0xd7,0xc7,0xc7,0x9b,0xd1,0x15,0xd1,0x10, /* 1600x1200 for LCDA */
+   0xb2,0x86,0xaf,0xb0,0xd2,0x2f,0x00,0x03,
+   0x00}},  /* 0x57 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 60 Hz */
+   0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+   0x01}},  /* 0x58 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xdc, /* 1280x768 (1280x1024) 75 Hz */
+   0x92,0x86,0xff,0x91,0x29,0x21,0x00,0x07,
+   0x01}},  /* 0x59 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xdc, /* 1280x768 (1280x1024) 85 Hz */
+   0x95,0x89,0xff,0x94,0x2f,0x21,0x00,0x07,
+   0x01}},  /* 0x5a */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x800 (1280x1024) 60 Hz */
+   0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+   0x01}},  /* 0x5b */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x800 (1280x1024) 75 Hz */
+   0xa2,0x86,0x1f,0xa1,0x29,0x01,0x00,0x07,
+   0x01}},  /* 0x5c */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x800 (1280x1024) 85 Hz */
+   0xa5,0x89,0x1f,0xa4,0x2f,0x01,0x00,0x07,
+   0x01}},  /* 0x5d */
+ {{0x7f,0x63,0x63,0x83,0x6d,0x1d,0x0b,0x3e, /* 800x480 (wide) 60 Hz */
+   0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x06,
+   0x00}},  /* 0x5e */
+ {{0xa0,0x7f,0x7f,0x84,0x85,0x97,0x52,0xf0, /* 1024x576 (wide) 60 Hz */
+   0x41,0x85,0x3f,0x40,0x53,0x00,0x00,0x02,
+   0x01}},  /* 0x5f */
+ {{0xc9,0x9f,0x9f,0x8d,0xb0,0x15,0xec,0xf0, /* 1280x720 (wide) 60 Hz */
+   0xd4,0x89,0xcf,0xd3,0xed,0x20,0x00,0x07,
+   0x01}},  /* 0x60 */
+ {{0xcb,0x9f,0x9f,0x8f,0xa5,0x13,0x5b,0xff, /* 1280x854-60 wide */
+   0x56,0x89,0x55,0x55,0x5c,0x30,0x00,0x07,
+   0x01}},  /* 0x61 */
+ {{0xce,0x9f,0x9f,0x92,0xa9,0x17,0x28,0xde, /* 1280x854 (1280x1024) 60 Hz */
+   0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+   0x41}},  /* 0x62 */
+ {{0xce,0x9f,0x9f,0x92,0xa5,0x17,0x28,0xde, /* 1280x854 (1280x1024) 75 Hz */
+   0xbd,0x81,0x55,0xbc,0x29,0x01,0x00,0x07,
+   0x41}},  /* 0x63 */
+ {{0xd3,0x9f,0x9f,0x97,0xab,0x1f,0x2e,0xde, /* 1280x854 (1280x1024) 85 Hz */
+   0xc0,0x84,0x55,0xbf,0x2f,0x01,0x00,0x07,
+   0x41}}   /* 0x64 */
+};
+
+static const struct SiS_MCLKData SiS310_MCLKData_0_315[] =
 {
        { 0x3b,0x22,0x01,143},
        { 0x5c,0x23,0x01,166},
@@ -616,7 +569,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_315[] =
        { 0x5c,0x23,0x01,166}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_650[] =
 {
        { 0x5a,0x64,0x82, 66},
        { 0xb3,0x45,0x82, 83},
@@ -628,7 +581,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_650[] =
        { 0x37,0x22,0x82,133}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_330[] =
 {
        { 0x5c,0x23,0x01,166},
        { 0x5c,0x23,0x01,166},
@@ -640,7 +593,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_330[] =
        { 0x79,0x06,0x01,250}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_660[] =
 {
        { 0x5c,0x23,0x82,166},
        { 0x5c,0x23,0x82,166},
@@ -652,7 +605,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_660[] =
        { 0x37,0x21,0x82,200}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_760[] =
 {
        { 0x37,0x22,0x82,133},
        { 0x5c,0x23,0x82,166},
@@ -664,7 +617,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_760[] =
        { 0x37,0x21,0x82,200}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_761[] =
 {
        { 0x37,0x22,0x82,133},  /* Preliminary */
        { 0x5c,0x23,0x82,166},
@@ -676,7 +629,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_761[] =
        { 0x37,0x21,0x82,200}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] =
+static const struct SiS_MCLKData SiS310_MCLKData_0_340[] =
 {
        { 0x79,0x06,0x01,250},
        { 0x7c,0x08,0x01,200},
@@ -688,9 +641,9 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_0_340[] =
        { 0x29,0x01,0x81,300}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
+static const struct SiS_MCLKData SiS310_MCLKData_1[] = /* ECLK */
 {
-        { 0x29,0x21,0x82,150},
+       { 0x29,0x21,0x82,150},
        { 0x5c,0x23,0x82,166},
        { 0x65,0x23,0x82,183},
        { 0x37,0x21,0x82,200},
@@ -700,7 +653,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_1[] = /* ECLK */
        { 0x37,0x22,0x82,133}
 };
 
-static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] =
+static const struct SiS_MCLKData SiS310_MCLKData_1_340[] =
 {
        { 0x7c,0x08,0x01,200},
        { 0x7c,0x08,0x01,200},
@@ -712,7 +665,7 @@ static const SiS_MCLKDataStruct SiS310_MCLKData_1_340[] =
        { 0x29,0x01,0x81,300}
 };
 
-static SiS_VCLKDataStruct SiS310_VCLKData[]=
+static struct SiS_VCLKData SiS310_VCLKData[] =
 {
        { 0x1b,0xe1, 25}, /* 0x00 */
        { 0x4e,0xe4, 28}, /* 0x01 */
@@ -805,7 +758,7 @@ static SiS_VCLKDataStruct SiS310_VCLKData[]=
        { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) */
        { 0x52,0x07,149}, /* 0x59 1280x960-85 */
        { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
-       { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
+       { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
        { 0x45,0x25, 83}, /* 0x5c 1280x800  */
        { 0x70,0x0a,147}, /* 0x5d 1680x1050 */
        { 0x70,0x24,162}, /* 0x5e 1600x1200 */
@@ -823,10 +776,19 @@ static SiS_VCLKDataStruct SiS310_VCLKData[]=
        { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
        { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
        { 0x45,0x25, 83}, /* 0x6c 1280x800 */
-       { 0x70,0x28, 90}  /* 0x6d 1152x864@60 */
+       { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+       { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+       { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+       { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+       { 0x2b,0xc2, 35}, /* 0x71 768x576@60 */
+       { 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+       { 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+       { 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+       { 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+       { 0x75,0x13, 84}  /* 0x76 1280x854 60Hz (wide) */
 };
 
-static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
+static struct SiS_VBVCLKData SiS310_VBVCLKData[] =
 {
        { 0x1b,0xe1, 25}, /* 0x00 */
        { 0x4e,0xe4, 28}, /* 0x01 */
@@ -858,12 +820,6 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
        { 0x5e,0x43,113}, /* 0x1b */
        { 0xbc,0x44,116}, /* 0x1c */
        { 0xe0,0x46,132}, /* 0x1d */
-#if 0
-       { 0xd4,0x28,135}, /* 0x1e */
-       { 0xea,0x2a,139}, /* 0x1f */
-       { 0x41,0x22,157}, /* 0x20 */
-       { 0x70,0x24,162}, /* 0x21 */
-#endif
        { 0xe2,0x46,135}, /* 0x1e */  /* 1280x1024-75, better clock for VGA2 */
        { 0xe5,0x46,139}, /* 0x1f */  /* 1024x768-120, better clock for VGA2 */
        { 0x15,0x01,157}, /* 0x20 */  /* 1280x1024-85, better clock for VGA2 */
@@ -912,7 +868,7 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
        { 0x34,0x61, 95}, /* 0x4b UNUSED */
        { 0x78,0x27,108}, /* 0x4c UNUSED */
        { 0x66,0x43,123}, /* 0x4d 1400x1050-60 */
-       { 0x41,0x4e, 21}, /* 0x4e UNUSED */
+       { 0x41,0x4e, 21}, /* 0x4e */
        { 0xa1,0x4a, 29}, /* 0x4f UNUSED */
        { 0x19,0x42, 42}, /* 0x50 UNUSED */
        { 0x54,0x46, 58}, /* 0x51 UNUSED */
@@ -925,7 +881,7 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
        { 0x30,0x23, 88}, /* 0x58 1360x768-62 (is 60Hz!) TEMP, UNUSED */
        { 0x52,0x07,149}, /* 0x59 1280x960-85  */
        { 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
-       { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
+       { 0x70,0x29, 81}, /* 0x5b 1280x768 LCD (TMDS) */
        { 0xce,0x1e, 73}, /* 0x5c 1280x800_2 LCD (SiS LVDS) - (CRT1: 45 25 83) */
        { 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
        { 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
@@ -943,57 +899,33 @@ static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
        { 0x7c,0x6b, 38}, /* 0x6a 960x540@60 */
        { 0xe3,0x56, 41}, /* 0x6b 960x600@60 */
        { 0x9c,0x62, 69}, /* 0x6c 1280x800 (SiS TMDS) (special) */
-       { 0x70,0x28, 90}  /* 0x6d 1152x864@60 */
+       { 0x70,0x28, 90}, /* 0x6d 1152x864@60 */
+       { 0x15,0xe1, 20}, /* 0x6e 640x400@60 (fake, not actually used) */
+       { 0x5f,0xc6, 33}, /* 0x6f 720x576@60 */
+       { 0x37,0x5a, 10}, /* 0x70 320x200@60 (fake, not actually used) */
+       { 0x2b,0xc2, 35}, /* 0x71 768@576@60 */
+       { 0xa8,0x42,131}, /* 0x72 1600x1200@60 for LCDA */
+       { 0x1b,0xc1, 34}, /* 0x73 800x480 60Hz (wide) */
+       { 0x41,0x64, 48}, /* 0x74 1024x576 60Hz (wide) */
+       { 0x52,0x27, 75}, /* 0x75 1280x720 60Hz (wide) */
+       { 0x75,0x13, 84}  /* 0x76 1280x854 60Hz (SiS LVDS) LCD */
 };
 
-static const DRAM4Type SiS310_SR15[8] = {
-       {0x00,0x04,0x60,0x60},
-       {0x0f,0x0f,0x0f,0x0f},
-       {0xba,0xba,0xba,0xba},
-       {0xa9,0xa9,0xac,0xac},
-       {0xa0,0xa0,0xa0,0xa8},
-       {0x00,0x00,0x02,0x02},
-       {0x30,0x30,0x40,0x40},
-       {0x00,0xa5,0xfb,0xf6}
-};
-
-#ifdef LINUX_KERNEL
-
-static UCHAR SiS310_SR07 = 0x18;
-
-static const DRAM4Type SiS310_CR40[5] = {
-       {0x77,0x77,0x33,0x33},
-       {0x77,0x77,0x33,0x33},
-       {0x00,0x00,0x00,0x00},
-       {0x5b,0x5b,0x03,0x03},
-       {0x00,0x00,0xf0,0xf8}
+static const unsigned char SiS310_SR15[4 * 8] =
+{
+       0x00,0x04,0x60,0x60,
+       0x0f,0x0f,0x0f,0x0f,
+       0xba,0xba,0xba,0xba,
+       0xa9,0xa9,0xac,0xac,
+       0xa0,0xa0,0xa0,0xa8,
+       0x00,0x00,0x02,0x02,
+       0x30,0x30,0x40,0x40,
+       0x00,0xa5,0xfb,0xf6
 };
 
-static UCHAR SiS310_CR49[] = {0xaa,0x88};
-static UCHAR SiS310_SR1F = 0x00;
-static UCHAR SiS310_SR21 = 0xa5;
-static UCHAR SiS310_SR22 = 0xfb;
-static UCHAR SiS310_SR23 = 0xf6;
-static UCHAR SiS310_SR24 = 0x0d;
-static UCHAR SiS310_SR25[] = {0x33,0x3};
-static UCHAR SiS310_SR31 = 0x00;
-static UCHAR SiS310_SR32 = 0x11;
-static UCHAR SiS310_SR33 = 0x00;
-static UCHAR SiS310_CRT2Data_1_2  = 0x00;
-static UCHAR SiS310_CRT2Data_4_D  = 0x00;
-static UCHAR SiS310_CRT2Data_4_E  = 0x00;
-static UCHAR SiS310_CRT2Data_4_10 = 0x80;
-static const USHORT SiS310_RGBSenseData    = 0xd1;
-static const USHORT SiS310_VideoSenseData  = 0xb9;
-static const USHORT SiS310_YCSenseData     = 0xb3;
-static const USHORT SiS310_RGBSenseData2   = 0x0190; 
-static const USHORT SiS310_VideoSenseData2 = 0x0174;
-static const USHORT SiS310_YCSenseData2    = 0x016b;
-#endif
-
-static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTbl[] =
 {
-        {{0x10,0x40}},
+       {{0x10,0x40}},
        {{0x10,0x40}},
        {{0x10,0x40}},
        {{0x10,0x40}},
@@ -1011,7 +943,7 @@ static const SiS_PanelDelayTblStruct SiS310_PanelDelayTbl[]=
        {{0x10,0x40}}
 };
 
-static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
+static const struct SiS_PanelDelayTbl SiS310_PanelDelayTblLVDS[] =
 {
        {{0x28,0xc8}},
        {{0x28,0xc8}},
@@ -1035,18 +967,18 @@ static const SiS_PanelDelayTblStruct SiS310_PanelDelayTblLVDS[]=
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-static const SiS_LCDDataStruct  SiS310_St2LCD1024x768Data[] =
+static const struct SiS_LCDData SiS310_St2LCD1024x768Data[] =
 {
        {   62,  25, 800, 546,1344, 806},
        {   32,  15, 930, 546,1344, 806},
-        {   62,  25, 800, 546,1344, 806},
+       {   62,  25, 800, 546,1344, 806},
        {  104,  45, 945, 496,1344, 806},
        {   62,  25, 800, 546,1344, 806},
        {   31,  18,1008, 624,1344, 806},
        {    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =
+static const struct SiS_LCDData SiS310_ExtLCD1024x768Data[] =
 {
        {   42,  25,1536, 419,1344, 806},
        {   48,  25,1536, 369,1344, 806},
@@ -1057,7 +989,7 @@ static const SiS_LCDDataStruct  SiS310_ExtLCD1024x768Data[] =
        {    1,   1,1344, 806,1344, 806}
 };
 
-static const SiS_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
+static const struct SiS_LCDData SiS310_St2LCD1280x1024Data[] =
 {
        {   22,   5, 800, 510,1650,1088},
        {   22,   5, 800, 510,1650,1088},
@@ -1069,7 +1001,7 @@ static const SiS_LCDDataStruct  SiS310_St2LCD1280x1024Data[] =
        {    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
+static const struct SiS_LCDData SiS310_ExtLCD1280x1024Data[] =
 {
        {  211,  60,1024, 501,1688,1066},
        {  211,  60,1024, 508,1688,1066},
@@ -1081,45 +1013,22 @@ static const SiS_LCDDataStruct  SiS310_ExtLCD1280x1024Data[] =
        {    1,   1,1688,1066,1688,1066}
 };
 
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_1024x768_1[] =
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_1024x768_1[] =
 {
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
      {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x2c,0x12,0x9a,0xae,0x88,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x25,0x12,0xc9,0xdc,0xb6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
      {{0x38,0x13,0x16,0x0c,0xe6,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x38,0x18,0x16,0x00,0x00,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x36,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
-/* *** LCDA *** */
-
-#if 0
-static const SiS_LVDSDataStruct  SiS_LCDA1600x1200Data_1[]=
-{ /* Clevo, 651+301C */
-       {1200, 450, 2048,1250},
-       {1200, 400, 2048,1250},
-       {1280, 450, 2048,1250},
-       {1280, 400, 2048,1250},
-       {1200, 530, 2048,1250},
-       {1360, 650, 2048,1250},
-       {1584, 818, 2048,1250},
-       {1688,1066, 2048,1250},
-       {1688,1066, 2048,1250},
-#if 0
-       {2048,1250, 2048,1250}   /* this should be correct */
-#endif
-#if 1
-       {2160,1250, 2048,1250}   /* ? */
-#endif
-};
-#endif
-
 /**************************************************************/
 /* LVDS, CHRONTEL ------------------------------------------- */
 /**************************************************************/
 
-static const SiS_LVDSDataStruct  SiS310_CHTVUPALData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -1130,7 +1039,7 @@ static const SiS_LVDSDataStruct  SiS310_CHTVUPALData[]=
        {1400,1000,1400,1000}
 };
 
-static const SiS_LVDSDataStruct  SiS310_CHTVOPALData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -1138,10 +1047,10 @@ static const SiS_LVDSDataStruct  SiS310_CHTVOPALData[]=
        {1008, 625,1008, 625},
        { 840, 625, 840, 625},
        { 944, 625, 944, 625},
-        {1400, 875,1400, 875}
+       {1400, 875,1400, 875}
 };
 
-static const SiS_LVDSDataStruct  SiS310_CHTVUPALMData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALMData[] =
 {
        { 840, 600, 840, 600},
        { 840, 600, 840, 600},
@@ -1149,10 +1058,10 @@ static const SiS_LVDSDataStruct  SiS310_CHTVUPALMData[]=
        { 840, 600, 840, 600},
        { 784, 600, 784, 600},
        {1064, 750,1064, 750},
-        {1160, 945,1160, 945}
+       {1160, 945,1160, 945}
 };
 
-static const SiS_LVDSDataStruct  SiS310_CHTVOPALMData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALMData[] =
 {
        { 840, 525, 840, 525},
        { 840, 525, 840, 525},
@@ -1160,10 +1069,10 @@ static const SiS_LVDSDataStruct  SiS310_CHTVOPALMData[]=
        { 840, 525, 840, 525},
        { 784, 525, 784, 525},
        {1040, 700,1040, 700},
-        {1160, 840,1160, 840}
+       {1160, 840,1160, 840}
 };
 
-static const SiS_LVDSDataStruct  SiS310_CHTVUPALNData[]=
+static const struct SiS_LVDSData SiS310_CHTVUPALNData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -1174,7 +1083,7 @@ static const SiS_LVDSDataStruct  SiS310_CHTVUPALNData[]=
        {1400,1000,1400,1000}
 };
 
-static const SiS_LVDSDataStruct  SiS310_CHTVOPALNData[]=
+static const struct SiS_LVDSData SiS310_CHTVOPALNData[] =
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -1182,10 +1091,10 @@ static const SiS_LVDSDataStruct  SiS310_CHTVOPALNData[]=
        {1008, 625,1008, 625},
        { 840, 625, 840, 625},
        { 944, 625, 944, 625},
-        {1400, 875,1400, 875}
+       {1400, 875,1400, 875}
 };
 
-static const SiS_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* (super overscan - no effect on 7019) */
+static const struct SiS_LVDSData SiS310_CHTVSOPALData[] =   /* (super overscan - no effect on 7019) */
 {
        {1008, 625,1008, 625},
        {1008, 625,1008, 625},
@@ -1196,1333 +1105,10 @@ static const SiS_LVDSDataStruct  SiS310_CHTVSOPALData[]=   /* (super overscan -
         {1400, 875,1400, 875}
 };
 
-
-static const SiS_LVDSDesStruct  SiS310_PanelType00_1[]=  /* 800x600 */
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType01_1[]=  /* 1024x768 */
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 805},
-       { 0, 0},
-       { 0, 0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType02_1[]=  /* 1280x1024 */
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 1065},
-       { 0, 0},
-       { 0, 0}
-};
-
-
-static const SiS_LVDSDesStruct  SiS310_PanelType03_1[]=
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType04_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType05_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType06_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType07_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType08_1[]=   /* 1400x1050 */
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType09_1[]=   /* 1280x768 */
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0a_1[]=  /* 1600x1200 */
-{
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0},
-       { 0, 0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0b_1[]=  /* 640x480_2 */
-{
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 8, 524},
-       { 0, 524}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0c_1[]=  /* 640x480_3 */
-{
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 0, 524},
-       { 8, 524},
-       { 0, 524}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0d_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0e_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0f_1[]=
-{
-       {1343, 798},
-       {1343, 794},
-       {1343, 798},
-       {1343, 794},
-       {1343,   0},
-       {1343,   0},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType00_2[]=
-{
-       {980, 528},
-       {980, 503},
-       {980, 528},
-       {980, 503},
-       {980, 568},
-       { 0, 628},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType01_2[]=
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 806},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType02_2[]=
-{
-       {1368, 754},
-       {1368, 729},
-       {1368, 754},
-       {1368, 729},
-       {1368, 794},
-       {1448, 854},
-       {1560, 938},
-       {   0,1066},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType03_2[]=
-{
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType04_2[]=
-{
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType05_2[]=
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType06_2[]=
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType07_2[]=
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType08_2[]=  /* 1400x1050 */
-{
-       {1308, 741},
-       {1308, 716},
-       {1308, 741},
-       {1308, 716},
-       {1308, 781},
-       {1388, 841},
-       {1500, 925},
-       {1628,1053},
-       {   0,1065},
-       {   0,   0},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType09_2[]= /* 1280x768 */
-{
-       {1083, 622},
-       {1083, 597},
-       {1083, 622},
-       {1083, 597},
-       {1083, 662},
-       {1163, 722},
-       {1286, 805},
-       {   0, 794},
-       {   0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0a_2[]=  /* 1600x1200 */
-{
-       {1568, 920},
-       {1568, 895},
-       {1568, 920},
-       {1568, 895},
-       {1568, 960},
-       {1648,1020},
-       {1760,1104},
-       {1888,1232},
-       {1948,1245},
-       {   0,   0}
-#if 0
-       {1568, 850},
-       {1568, 825},
-       {1568, 850},
-       {1568, 825},
-       {1568, 890},
-       {1648, 950},
-       {1760,1034},
-       {1888,1162},
-       {1948,1175},
-       {   0,   0}
-#endif
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0b_2[]=  /* 640x480_2 */
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0c_2[]=  /* 640x480_3 */
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0d_2[]=
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0e_2[]=
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelType0f_2[] =
-{
-       {1152, 622},
-       {1152, 597},
-       {1152, 622},
-       {1152, 597},
-       {1152, 662},
-       {1232, 722},
-       { 0, 805},
-       { 0, 794},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_1[]=
-{
-       { 8,   0},
-       { 8,   0},
-       { 8,   0},
-       { 8,   0},
-       { 8,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0, 806},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS310_PanelTypeNS_2[] =
-{
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0},
-       { 0 , 0}
-};
-
-/* CRT1 CRTC for SlaveModes and LCDA */
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1[] =
-{
- {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
-   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-   0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0xaa,0x1f,
-   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-   0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0x78,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00 }},
- {{0x6b,0x4f,0x8f,0x55,0x85,0xfa,0x1f,
-   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-   0x00 }},
- {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_1_H[] =
-{
- {{0x43,0x27,0x87,0x2d,0x1d,0xaa,0x1f,
-   0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
-   0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f,
-   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-   0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0x78,0x1f,
-   0x5e,0x83,0x5d,0x79,0x10,0x00,0x05,
-   0x00 }},
- {{0x43,0x27,0x87,0x2d,0x1d,0xfa,0x1f,
-   0xe0,0x85,0xdf,0xfb,0x10,0x00,0x05,
-   0x00 }},
- {{0x4d,0x31,0x91,0x37,0x07,0x72,0xf0,
-   0x58,0x8d,0x57,0x73,0x20,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2[]=
-{
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-   0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
-   0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-   0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06,
-   0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-   0xff,0x84,0x8f,0x73,0x00,0x00,0x06,
-   0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0x3e,
-   0xe6,0x8b,0x5d,0x73,0x00,0x00,0x06,
-   0x00 }},
- {{0x7f,0x4f,0x83,0x62,0x12,0x72,0xba,
-   0x27,0x8c,0xdf,0x73,0x00,0x00,0x06,
-   0x00 }},
- {{0x7f,0x63,0x83,0x69,0x19,0x72,0xf0,
-   0x58,0x8d,0x57,0x73,0x20,0x00,0x06,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1800x600_2_H[] =
-{
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
-   0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
-   0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
-   0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01,
-   0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
-   0xff,0x84,0x8f,0x73,0x00,0x00,0x01,
-   0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0x3e,
-   0xd6,0x8b,0x5d,0x73,0x00,0x00,0x01,
-   0x00 }},
- {{0x57,0x27,0x9b,0x3a,0x0a,0x72,0xba,
-   0x27,0x8c,0xdf,0x73,0x00,0x00,0x01,
-   0x00 }},
- {{0x4d,0x31,0x91,0x3a,0x0a,0x72,0xf0,
-   0x63,0x88,0x57,0x73,0x00,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1[] =
-{
- {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0xb4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x82,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x05,
-   0x00}},
- {{0x73,0x4f,0x97,0x53,0x84,0x04,0x3e,
-   0xE2,0x89,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x87,0x63,0x8B,0x67,0x18,0x7c,0xf0,
-   0x5A,0x81,0x57,0x7D,0x00,0x00,0x06,
-   0x01}},
- {{0xA3,0x7f,0x87,0x83,0x94,0x24,0xf5,
-   0x02,0x89,0xFf,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_1_H[] =
-{
- {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
-   0x00 }},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x83,0x01,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0xb4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x82,0x1f,
-   0x60,0x87,0x5D,0x83,0x01,0x00,0x05,
-   0x00}},
- {{0x4b,0x27,0x8f,0x2b,0x1c,0x04,0x3e,
-   0xE2,0x89,0xDf,0x05,0x00,0x00,0x05,
-   0x00}},
- {{0x55,0x31,0x99,0x35,0x06,0x7c,0xf0,
-   0x5A,0x81,0x57,0x7D,0x00,0x00,0x01,
-   0x01}},
- {{0x63,0x3F,0x87,0x43,0x94,0x24,0xf5,
-   0x02,0x89,0xFf,0x25,0x10,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
-   0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x3e,0x85,0x5d,0x25,0x10,0x00,0x06,
-   0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x57,0x8e,0x8f,0x25,0x30,0x00,0x06,
-   0x00 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x3e,0x85,0x5d,0x25,0x10,0x00,0x06,
-   0x01 }},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x7f,0x86,0xdf,0x25,0x10,0x00,0x06,
-   0x00 }},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xbb,0x82,0x57,0x25,0x10,0x00,0x02,
-   0x01 }},
- {{0xa3,0x7f,0x87,0x83,0x94,0x24,0xf5,
-   0x02,0x89,0xff,0x25,0x10,0x00,0x02,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11024x768_2_H[] =
-{
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x57,0x8e,0x8f,0x25,0x30,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x3e,0x85,0x5d,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x7b,0x27,0x9f,0x46,0x97,0x24,0xbb,
-   0x7f,0x86,0xdf,0x25,0x10,0x00,0x01,
-   0x00 }},
- {{0x71,0x31,0x95,0x46,0x97,0x24,0xf1,
-   0xbb,0x82,0x57,0x25,0x10,0x00,0x01,
-   0x01 }},
- {{0x63,0x3f,0x87,0x46,0x97,0x24,0xf5,
-   0x0f,0x86,0xff,0x25,0x30,0x00,0x01,
-   0x01 }}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1[] =
-{
- {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0xb8,0x1f,
-   0x90,0x84,0x8f,0xb9,0x30,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x86,0x1f,
-   0x5e,0x82,0x5d,0x87,0x10,0x00,0x06,
-   0x00}},
- {{0x7e,0x4f,0x82,0x58,0x04,0x08,0x3e,
-   0xe0,0x84,0xdf,0x09,0x00,0x00,0x06,
-   0x00}},
- {{0x92,0x63,0x96,0x6c,0x18,0x80,0xf0,
-   0x58,0x8c,0x57,0x81,0x20,0x00,0x06,
-   0x01}},
- {{0xae,0x7f,0x92,0x88,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0x29,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_1_H[] =
-{
- {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x87,0x10,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0xb8,0x1f,
-   0x90,0x84,0x8f,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x86,0x1f,
-   0x5e,0x82,0x5d,0x87,0x10,0x00,0x05,
-   0x01}},
- {{0x56,0x27,0x9a,0x31,0x1c,0x08,0x3e,
-   0xe0,0x84,0xdf,0x09,0x00,0x00,0x05,
-   0x00}},
- {{0x60,0x31,0x84,0x3a,0x86,0x80,0xf0,
-   0x58,0x8c,0x57,0x81,0x20,0x00,0x01,
-   0x01}},
- {{0x6e,0x3f,0x92,0x48,0x94,0x28,0xf5,
-   0x00,0x84,0xff,0x29,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2[] =
-{
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
-   0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
-   0xaf,0x83,0x44,0x43,0x21,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
-   0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
-   0xaf,0x83,0x44,0x43,0x21,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x81,0x8f,0x28,0x92,
-   0xf0,0x84,0x85,0x84,0x11,0x00,0x02,
-   0x01}},
- {{0xce,0x63,0x92,0x8b,0x19,0x28,0xd4,
-   0x3f,0x83,0x57,0x29,0x01,0x00,0x03,
-   0x01}},
- {{0xce,0x7f,0x92,0x99,0x07,0x28,0xd4,
-   0x93,0x87,0xff,0x29,0x21,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11280x1024_2_H[] =
-{
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
-   0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
-   0xaf,0x83,0x44,0x43,0x21,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
-   0xc8,0x8c,0x5d,0x5c,0x01,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
-   0xfa,0x83,0x44,0x43,0x31,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x59,0x07,0x28,0x92,
-   0xf0,0x84,0x85,0x84,0x11,0x00,0x06,
-   0x01}},
- {{0x9c,0x31,0x80,0x59,0x87,0x28,0xd4,
-   0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
-   0x01}},
- {{0x8e,0x3f,0x92,0x59,0x07,0x28,0xd4,
-   0x93,0x87,0xff,0x29,0x21,0x00,0x06,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1[] =
-{
-  {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-    0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-    0x5e,0x81,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-    0x90,0x83,0x8f,0x9f,0x30,0x00,0x05,
-    0x00}},
-  {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-    0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-    0x00}},
-  {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f,
-    0xdf,0x82,0xdf,0xef,0x10,0x00,0x05,
-    0x00}},
-  {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0,
-    0x57,0x8e,0x57,0x67,0x20,0x00,0x06,
-    0x01}},
-  {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf1,
-    0xff,0x86,0xff,0x0f,0x10,0x00,0x02,
-    0x01,}},
-  {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0xde,
-    0xff,0x86,0xff,0x0f,0x01,0x00,0x07,
-    0x01}},
-  {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10,
-    0x19,0x80,0x19,0x29,0x0f,0x00,0x03,
-    0x00}}
-#if 0
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x9e,0x1f,
-   0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x6f,0x4f,0x93,0x54,0x82,0xee,0x1f,
-   0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
-   0x00}},
- {{0x83,0x63,0x87,0x68,0x16,0x66,0xf0,
-   0x5a,0x8e,0x57,0x67,0x20,0x00,0x06,
-   0x01}},
- {{0x9f,0x7f,0x83,0x84,0x92,0x0e,0xf5,
-   0x02,0x86,0xff,0x0f,0x10,0x00,0x02,
-   0x01}},
- {{0xbf,0x9f,0x83,0xa4,0x12,0x0e,0x5a,
-   0x02,0x86,0xff,0x0f,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0xae,0x92,0xb3,0x01,0x28,0x10,
-   0x1a,0x80,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-#endif   
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_1_H[] =
-{
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
-   0x8f,0x81,0x8f,0x9f,0x30,0x00,0x05,
-  0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
-   0x90,0x83,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
-   0xdf,0x86,0xdf,0xef,0x10,0x00,0x05,
-   0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
-   0x57,0x8e,0x57,0x67,0x20,0x00,0x01,
-   0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf1,
-   0xff,0x86,0xff,0x0f,0x10,0x00,0x01,
-   0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-   0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
-   0x01}},
- {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10,
-   0x1c,0x80,0x19,0x29,0x0b,0x00,0x05,
-   0x00}}
-#if 0
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
-   0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
-   0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
-   0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
-   0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
-   0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
-   0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
-   0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
-   0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-   0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
-   0x01}},
- {{0x76,0x56,0x9a,0x5b,0x89,0x28,0x10,
-   0x1c,0x80,0x19,0x29,0x0b,0x00,0x05,
-   0x00}}
-#endif   
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2[] =
-{
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
-   0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
-   0xbe,0x82,0x44,0x43,0x01,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
-   0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
-   0xbe,0x82,0x44,0x43,0x01,0x00,0x02,
-   0x01}},
- {{0xce,0x72,0x91,0x84,0x92,0x28,0x92,
-   0xff,0x83,0x85,0x84,0x11,0x00,0x02,
-   0x01}},
- {{0xce,0x63,0x92,0x8e,0x1c,0x28,0xd4,
-   0x3f,0x83,0x57,0x29,0x01,0x00,0x03,
-   0x01}},
- {{0xce,0x7f,0x92,0x9c,0x0a,0x28,0xd4,
-   0x93,0x87,0xff,0x29,0x21,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xac,0x1a,0x28,0x5a,
-   0x13,0x87,0xff,0x29,0x29,0x00,0x07,
-   0x01}},
- {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10,
-   0x20,0x84,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-#if 0
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x29,0x01,0x00,0x03,
-   0x01}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x29,0x21,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9a,
-   0xc2,0x86,0x5d,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x4f,0x92,0x8c,0x1a,0x28,0x9e,
-   0x03,0x87,0xdf,0x29,0x01,0x00,0x03,
-   0x00}},
- {{0xce,0x63,0x92,0x96,0x04,0x28,0xd4,
-   0x3f,0x83,0x57,0x29,0x01,0x00,0x07,
-   0x01}},
- {{0xce,0x7f,0x92,0xa4,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0x29,0x21,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xb4,0x02,0x28,0x5a,
-   0x13,0x87,0xff,0x29,0x29,0x00,0x03,
-   0x01}},
- {{0xce,0xae,0x92,0xbc,0x0a,0x28,0x10,
-   0x20,0x84,0x19,0x29,0x0f,0x00,0x03,
-   0x00}}
-#endif   
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11400x1050_2_H[] =
-{
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
-   0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
-   0xbe,0x82,0x44,0x43,0x01,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
-   0xd7,0x8b,0x5d,0x5c,0x21,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
-   0xbe,0x82,0x44,0x43,0x01,0x00,0x06,
-   0x01}},
- {{0xa6,0x4a,0x89,0x5c,0x0a,0x28,0x92,
-   0xff,0x83,0x85,0x84,0x11,0x00,0x06,
-   0x01}},
- {{0x9c,0x31,0x80,0x5c,0x8a,0x28,0xd4,
-   0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
-   0x01}},
- {{0x8e,0x3f,0x92,0x5c,0x0a,0x28,0xd4,
-   0x93,0x87,0xff,0x29,0x21,0x00,0x06,
-   0x01}},
- {{0x7e,0x4f,0x82,0x5c,0x0a,0x28,0x5a,
-   0x13,0x87,0xff,0x29,0x29,0x00,0x06,
-   0x01}},
- {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10,
-   0x20,0x84,0x19,0x29,0x0f,0x00,0x05,
-   0x00}}
-#if 0
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xdb,0x8f,0x8f,0x29,0x21,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9a,
-   0xc2,0x86,0x5d,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0xa6,0x27,0x8a,0x64,0x92,0x28,0x9e,
-   0x03,0x87,0xdf,0x29,0x01,0x00,0x06,
-   0x00}},
- {{0x9c,0x31,0x80,0x64,0x92,0x28,0xd4,
-   0x3f,0x83,0x57,0x29,0x01,0x00,0x06,
-   0x01}},
- {{0x8e,0x3f,0x92,0x64,0x12,0x28,0xd4,
-   0x93,0x87,0xff,0x29,0x21,0x00,0x06,
-   0x01}},
- {{0x7e,0x4f,0x82,0x64,0x12,0x28,0x5a,
-   0x13,0x87,0xff,0x29,0x29,0x00,0x06,
-   0x01}},
- {{0x76,0x56,0x9a,0x64,0x92,0x28,0x10,
-   0x20,0x84,0x19,0x29,0x0f,0x00,0x05,
-   0x00}}
-#endif   
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1[] =
-{
- {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
-   0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
-   0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0x06,0x3E,
-   0xB3,0x86,0x8F,0x07,0x20,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
-   0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0x56,0xBA,
-   0x03,0x86,0xDF,0x57,0x00,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x9B,0x6F,0x07,0xCE,0xF0,
-   0x7B,0x8E,0x57,0xCF,0x20,0x00,0x02,
-   0x01}},
- {{0xB3,0x7F,0x97,0x8B,0x83,0x76,0xF5,
-   0x23,0x86,0xFF,0x77,0x10,0x00,0x06,
-   0x01}},
- {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A,
-   0x23,0x86,0xFF,0x77,0x09,0x00,0x03,
-   0x01}},
- {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10,
-   0x3D,0x80,0x19,0x91,0x0F,0x00,0x03,
-   0x00}},
- {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11,
-   0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07,
-   0x00}}
-#if 0
- {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
-   0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f,
-   0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0xc0,0x1f,
-   0x90,0x84,0x8f,0xc1,0x30,0x00,0x06,
-   0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x8e,0x1f,
-   0x5e,0x82,0x5d,0x8f,0x10,0x00,0x06,
-   0x00}},
- {{0x83,0x4f,0x87,0x51,0x09,0x10,0x3e,
-   0xe0,0x84,0xdf,0x11,0x00,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x9b,0x65,0x1d,0x88,0xf0,
-   0x58,0x8c,0x57,0x89,0x20,0x00,0x06,
-   0x01}},
- {{0xb3,0x7f,0x97,0x81,0x99,0x30,0xf5,
-   0x00,0x84,0xff,0x31,0x10,0x00,0x02,
-   0x01}},
- {{0xd3,0x9f,0x97,0xa1,0x19,0x30,0x5a,
-   0x00,0x84,0xff,0x31,0x09,0x00,0x07,
-   0x01}},
- {{0xe2,0xae,0x86,0xb0,0x88,0x4a,0x10,
-   0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x03,
-   0x00}},
- {{0xfb,0xc7,0x9f,0xc9,0x81,0xe0,0x10,
-   0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x07,
-   0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_1_H[] =
-{
- {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
-   0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
-   0x00}},
- {{0x5B,0x27,0x9F,0x29,0x01,0x8E,0x1F,
-   0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
-   0x00}},
- {{0x5B,0x27,0x9F,0x33,0x0B,0x06,0x2E,
-   0xB3,0x86,0x8F,0x07,0x20,0x00,0x01,
-   0x00}},
- {{0x83,0x4F,0x87,0x5B,0x13,0xD4,0x1F,
-   0x81,0x84,0x5D,0xD5,0x10,0x00,0x06,
-   0x00}},
- {{0x5B,0x27,0x9F,0x33,0x0B,0x56,0xBA,
-   0x03,0x86,0xDF,0x57,0x00,0x00,0x01,
-   0x00}},
- {{0x65,0x31,0x89,0x3D,0x95,0xCE,0xF0,
-   0x7B,0x8E,0x57,0xCF,0x20,0x00,0x01,
-   0x01}},
- {{0x73,0x3F,0x97,0x4B,0x83,0x76,0xF5,
-   0x23,0x86,0xFF,0x77,0x10,0x00,0x05,
-   0x01}},
- {{0xD3,0x9F,0x97,0xAB,0x03,0x76,0x5A,
-   0x23,0x86,0xFF,0x77,0x09,0x00,0x03,
-   0x01}},
- {{0xE2,0xAE,0x86,0xBA,0x92,0x90,0x10,
-   0x3D,0x80,0x19,0x91,0x0F,0x00,0x03,
-   0x00}},
- {{0x97,0x63,0x9B,0x6F,0x07,0xE0,0x10,
-   0xB0,0x84,0xAF,0xE1,0x2F,0x00,0x06,
-   0x00}}
-#if 0
- {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f,
-   0x90,0x84,0x8f,0xc1,0x30,0x00,0x01,
-   0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f,
-   0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01,
-   0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0xc0,0x1f,
-   0x90,0x84,0x8f,0xc1,0x30,0x00,0x01,
-   0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x8e,0x1f,
-   0x5e,0x82,0x5d,0x8f,0x10,0x00,0x01,
-   0x00}},
- {{0x5b,0x27,0x9f,0x29,0x01,0x10,0x3e,
-   0xe0,0x84,0xdf,0x11,0x00,0x00,0x01,
-   0x00}},
- {{0x65,0x31,0x89,0x33,0x8b,0x88,0xf0,
-   0x58,0x8c,0x57,0x89,0x20,0x00,0x01,
-   0x01}},
- {{0x73,0x3f,0x97,0x41,0x99,0x30,0xf5,
-   0x00,0x84,0xff,0x31,0x10,0x00,0x01,
-   0x01}},
- {{0x83,0x4f,0x87,0x51,0x09,0x30,0x5a,
-   0x00,0x84,0xff,0x31,0x09,0x00,0x06,
-   0x01}},
- {{0x8a,0x56,0x8e,0x58,0x10,0x4a,0x10,
-   0x1a,0x8e,0x19,0x4b,0x2f,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x9b,0x65,0x1d,0xe0,0x10,
-   0xb0,0x84,0xaf,0xe1,0x2f,0x00,0x06,
-   0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2[] =
-{
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
-   0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
-   0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
-   0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07,
-   0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
-   0x43,0x86,0xDB,0xDA,0x11,0x00,0x07,
-   0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x97,
-   0x2A,0x8D,0xC2,0xC1,0x11,0x00,0x07,
-   0x01}},
- {{0xFB,0x87,0x86,0x97,0x0F,0x26,0x9F,
-   0x6B,0x8E,0x03,0x02,0x01,0x00,0x07,
-   0x01}},
- {{0xFB,0x63,0x9F,0xA1,0x99,0x26,0xD5,
-   0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x07,
-   0x01}},
- {{0xFB,0x7F,0x9F,0xAF,0x87,0x26,0xDD,
-   0xFB,0x8E,0x13,0x12,0x31,0x00,0x03,
-   0x01}},
- {{0xFB,0x9F,0x9F,0xBF,0x97,0x26,0x5B,
-   0x7B,0x8E,0xFF,0x27,0x39,0x00,0x03,
-   0x01}},
- {{0xFB,0xAE,0x9F,0xC6,0x9E,0x26,0x11,
-   0x88,0x8B,0x19,0x27,0x1F,0x00,0x03,
-   0x00}},
- {{0xFB,0xC7,0x9F,0xD3,0x8B,0x26,0x11,
-   0xD3,0x86,0xAF,0x27,0x3F,0x00,0x07,
-   0x00}}
-#if 0
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
-   0x20,0x84,0xb9,0xb8,0x01,0x00,0x07,
-   0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
-   0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07,
-   0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
-   0x20,0x84,0xb9,0xb8,0x01,0x00,0x07,
-   0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
-   0x07,0x8b,0xa0,0x9f,0x01,0x00,0x07,
-   0x01}},
- {{0xfb,0x88,0x87,0x90,0x08,0xe0,0x96,
-   0x48,0x8c,0xe1,0xe0,0x11,0x00,0x07,
-   0x01}},
- {{0xfb,0x63,0x9f,0x9a,0x92,0xe0,0xd4,
-   0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x07,
-   0x01}},
- {{0xfb,0x7f,0x9f,0xa8,0x80,0xe0,0xd4,
-   0xef,0x83,0xff,0xe1,0x21,0x00,0x03,
-   0x01}},
- {{0xfb,0x9f,0x9f,0xb8,0x90,0xe0,0x5a,
-   0x6f,0x83,0xff,0xe1,0x29,0x00,0x03,
-   0x01}},
- {{0xfb,0xae,0x9f,0xbf,0x97,0xe0,0x10,
-   0x7c,0x80,0x19,0xe1,0x0f,0x00,0x03,
-   0x00}},
- {{0xfb,0xc7,0x9f,0xc9,0x84,0xe0,0x10,
-   0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x07,
-   0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT11600x1200_2_H[] =
-{
- {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
-   0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
-   0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
-   0x6B,0x8E,0x83,0x82,0x01,0x00,0x03,
-   0x01}},
- {{0xD3,0x5F,0x9E,0x6F,0x07,0x26,0x97,
-   0x43,0x86,0xDB,0xDA,0x11,0x00,0x02,
-   0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
-   0x07,0x8B,0xA0,0x9F,0x01,0x00,0x02,
-   0x01}},
- {{0xD3,0x27,0x97,0x6F,0x07,0x26,0x97,
-   0x6B,0x8E,0x83,0x82,0x01,0x00,0x03,
-   0x01}},
- {{0xC9,0x31,0x8D,0x6F,0x07,0x26,0xD5,
-   0xA7,0x8A,0xBF,0xBE,0x01,0x00,0x03,
-   0x01}},
- {{0xBB,0x3F,0x9F,0x6F,0x87,0x26,0xDD,
-   0xFB,0x8E,0x13,0x12,0x31,0x00,0x02,
-   0x01}},
- {{0xAB,0x4F,0x8F,0x68,0x80,0xE0,0x5A,
-   0x6F,0x83,0xFF,0xE1,0x29,0x00,0x02,
-   0x01}},
- {{0xA3,0x56,0x87,0x67,0x9F,0xE0,0x10,
-   0x7C,0x80,0x19,0xE1,0x0F,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x9B,0x68,0x00,0xE0,0x10,
-   0xC7,0x8B,0xAF,0xE1,0x0F,0x00,0x02,
-   0x00}}
-#if 0
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
-   0x20,0x84,0xb9,0xb8,0x01,0x00,0x02,
-   0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
-   0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02,
-   0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
-   0x20,0x84,0xb9,0xb8,0x01,0x00,0x02,
-   0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
-   0x07,0x8b,0xa0,0x9f,0x01,0x00,0x02,
-   0x01}},
- {{0xd3,0x60,0x9f,0x68,0x00,0xe0,0x96,
-   0x48,0x8c,0xe1,0xe0,0x11,0x00,0x02,
-   0x01}},
- {{0xc9,0x31,0x8d,0x68,0x00,0xe0,0xd4,
-   0x9b,0x8f,0x9d,0x9c,0x21,0x00,0x03,
-   0x01}},
- {{0xbb,0x3f,0x9f,0x68,0x80,0xe0,0xd4,
-   0xef,0x83,0xff,0xe1,0x21,0x00,0x02,
-   0x01}},
- {{0xab,0x4f,0x8f,0x68,0x80,0xe0,0x5a,
-   0x6f,0x83,0xff,0xe1,0x29,0x00,0x02,
-   0x01}},
- {{0xa3,0x56,0x87,0x67,0x9f,0xe0,0x10,
-   0x7c,0x80,0x19,0xe1,0x0f,0x00,0x06,
-   0x00}},
- {{0x97,0x63,0x9b,0x68,0x00,0xe0,0x10,
-   0xc7,0x8b,0xaf,0xe1,0x0f,0x00,0x02,
-   0x00}}
-#endif
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xce,0x9f,0x92,0xa8,0x14,0x28,0x5a,
-   0x00,0x84,0xff,0x29,0x09,0x00,0x07,
-   0x01}},
- {{0xce,0x9f,0x92,0xa9,0x17,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x07,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS310_LVDSCRT1XXXxXXX_1_H[] =
-{
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x30,0x00,0x00,
-   0x00}},
- {{0x38,0x27,0x9c,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}},
- {{0x4d,0x31,0x91,0x3b,0x03,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x01,
-   0x01}},
- {{0x63,0x3f,0x87,0x4a,0x92,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-
 /* CRT1 CRTC for Chrontel TV slave modes */
 
-static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =
-{ 
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UNTSC[] =
+{
  {{0x64,0x4f,0x88,0x56,0x9f,0x56,0x3e,
    0xe8,0x84,0x8f,0x57,0x20,0x00,0x01,
    0x00 }},
@@ -2546,7 +1132,7 @@ static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UNTSC[] =
    0x01}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1ONTSC[] =
 {
  {{0x63,0x4f,0x87,0x5a,0x9f,0x0b,0x3e,
    0xc0,0x84,0x8f,0x0c,0x20,0x00,0x01,
@@ -2571,8 +1157,8 @@ static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1ONTSC[] =
    0x01 }}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =
-{ 
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1UPAL[] =
+{
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf8,0x83,0x8f,0x70,0x20,0x00,0x05,
    0x00 }},
@@ -2596,7 +1182,7 @@ static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1UPAL[] =
    0x01}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
+static const struct SiS_LVDSCRT1Data SiS310_CHTVCRT1OPAL[] =
 {
  {{0x79,0x4f,0x9d,0x5a,0x90,0x6f,0x3e,
    0xf0,0x83,0x8f,0x70,0x20,0x00,0x05,
@@ -2621,8 +1207,7 @@ static const SiS_LVDSCRT1DataStruct  SiS310_CHTVCRT1OPAL[] =
    0x01 }}
 };
 
-
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UNTSC[] =
 {
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x4a,0x77,0xbb,0x94,0x84,0x48,0xfe,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2642,7 +1227,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UNTSC[] =
       for PAL-M and PAL-N all above is corrected.
     */
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_ONTSC[] =
 {
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x49,0x77,0xbb,0x7b,0x84,0x34,0x00,0x50,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2653,7 +1238,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_ONTSC[] =
  {{0xed,0x77,0xbb,0x66,0x8c,0x21,0x02,0x5a,0x04,0x00,0x80,0x1f,0x9f,0xc1,0x0c,0x00}}
 };
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPAL[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2664,7 +1249,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPAL[] =
  {{0xe5,0x7f,0xb7,0x1d,0xa7,0x3e,0x04,0x5a,0x05,0x00,0x80,0x20,0x3e,0xe4,0x22,0x00}}
 };
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPAL[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x83,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2675,7 +1260,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPAL[] =
  {{0xe4,0x7f,0xb7,0x1e,0xaf,0x29,0x37,0x5a,0x05,0x00,0x80,0x25,0x8c,0xb2,0x2a,0x00}}
 };
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALM[] =
 {
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x52,0x77,0xbb,0x94,0x84,0x48,0xfe,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2691,7 +1276,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALM[] =
 #endif
 };
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALM[] =
 {
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
  {{0x51,0x77,0xbb,0x7b,0x84,0x34,0x00,0x83,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x01}},
@@ -2707,7 +1292,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALM[] =
 #endif
 };
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_UPALN[] =
 {
  {{0x41,0x7f,0xb7,0x34,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x80,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -2723,7 +1308,7 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_UPALN[] =
 #endif
 };
 
-static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
+static const struct SiS_CHTVRegData SiS310_CHTVReg_OPALN[] =
 {
  {{0x41,0x7f,0xb7,0x36,0xad,0x50,0x34,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
  {{0x41,0x7f,0xb7,0x86,0x85,0x50,0x00,0x6e,0x05,0x00,0x80,0x00,0x00,0x00,0x00,0x03}},
@@ -2739,16 +1324,16 @@ static const SiS_CHTVRegDataStruct SiS310_CHTVReg_OPALN[] =
 #endif
 };
 
-static const UCHAR SiS310_CHTVVCLKUNTSC[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53};
-static const UCHAR SiS310_CHTVVCLKONTSC[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51};
+static const unsigned char SiS310_CHTVVCLKUNTSC[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKONTSC[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
 
-static const UCHAR SiS310_CHTVVCLKUPAL[]  = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54};
-static const UCHAR SiS310_CHTVVCLKOPAL[]  = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52};
+static const unsigned char SiS310_CHTVVCLKUPAL[]  = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPAL[]  = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
 
-static const UCHAR SiS310_CHTVVCLKUPALM[] = {0x41,0x41,0x41,0x41,0x42,0x46,0x53};
-static const UCHAR SiS310_CHTVVCLKOPALM[] = {0x48,0x48,0x48,0x48,0x45,0x43,0x51};
+static const unsigned char SiS310_CHTVVCLKUPALM[] = { 0x41,0x41,0x41,0x41,0x42,0x46,0x53 };
+static const unsigned char SiS310_CHTVVCLKOPALM[] = { 0x48,0x48,0x48,0x48,0x45,0x43,0x51 };
 
-static const UCHAR SiS310_CHTVVCLKUPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4a,0x54};
-static const UCHAR SiS310_CHTVVCLKOPALN[] = {0x47,0x47,0x47,0x47,0x48,0x4f,0x52};
+static const unsigned char SiS310_CHTVVCLKUPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4a,0x54 };
+static const unsigned char SiS310_CHTVVCLKOPALN[] = { 0x47,0x47,0x47,0x47,0x48,0x4f,0x52 };
 
 
index aaed8c2b4a64d1fbd55c3b003077c9dcb237dc5f..f7c0046e5b1d138ecfa629dbc428a255923feef8 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_FB_SIS) += sisfb.o
 
-sisfb-objs := sis_main.o sis_accel.o init.o init301.o
+sisfb-objs := sis_main.o sis_accel.o init.o init301.o initextlfb.o
index ecfd72178dbb3fce2cc0d8b9d9b8b338b9dbcc3e..2ab3868efde30dd39449e103117324eb461d6453 100644 (file)
@@ -2,11 +2,12 @@
 /* $XdotOrg$ */
 /*
  * Mode initializing code (CRT1 section) for
- * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ * for SiS 300/305/540/630/730,
+ *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ *     XGI Volari V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
  * Used by permission.
- *
- * TW says: This code looks awful, I know. But please don't do anything about
- * this otherwise debugging will be hell.
- * The code is extremely fragile as regards the different chipsets, different
- * video bridges and combinations thereof. If anything is changed, extreme
- * care has to be taken that that change doesn't break it for other chipsets,
- * bridges or combinations thereof.
- * All comments in this file are by me, regardless if they are marked TW or not.
- *
  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "init.h"
 
 #ifdef SIS300
 
 #if defined(SIS300) || defined(SIS315H)
 static void
-InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitCommonPointer(struct SiS_Private *SiS_Pr)
 {
+   SiS_Pr->SiS_SModeIDTable  = SiS_SModeIDTable;
    SiS_Pr->SiS_StResInfo     = SiS_StResInfo;
    SiS_Pr->SiS_ModeResInfo   = SiS_ModeResInfo;
    SiS_Pr->SiS_StandTable    = SiS_StandTable;
 
-   SiS_Pr->SiS_NTSCPhase     = SiS_NTSCPhase;
-   SiS_Pr->SiS_PALPhase      = SiS_PALPhase;
-   SiS_Pr->SiS_NTSCPhase2    = SiS_NTSCPhase2;
-   SiS_Pr->SiS_PALPhase2     = SiS_PALPhase2;
-   SiS_Pr->SiS_PALMPhase     = SiS_PALMPhase;
-   SiS_Pr->SiS_PALNPhase     = SiS_PALNPhase;
-   SiS_Pr->SiS_PALMPhase2    = SiS_PALMPhase2;
-   SiS_Pr->SiS_PALNPhase2    = SiS_PALNPhase2;
-   SiS_Pr->SiS_SpecialPhase  = SiS_SpecialPhase;
-   SiS_Pr->SiS_SpecialPhaseM = SiS_SpecialPhaseM;
-   SiS_Pr->SiS_SpecialPhaseJ = SiS_SpecialPhaseJ;
-
    SiS_Pr->SiS_NTSCTiming     = SiS_NTSCTiming;
    SiS_Pr->SiS_PALTiming      = SiS_PALTiming;
    SiS_Pr->SiS_HiTVSt1Timing  = SiS_HiTVSt1Timing;
@@ -137,6 +122,7 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    SiS_Pr->SiS_ExtLCD1280x768_2Data = SiS_ExtLCD1280x768_2Data;
    SiS_Pr->SiS_LCD1280x800Data      = SiS_LCD1280x800Data;
    SiS_Pr->SiS_LCD1280x800_2Data    = SiS_LCD1280x800_2Data;
+   SiS_Pr->SiS_LCD1280x854Data      = SiS_LCD1280x854Data;
    SiS_Pr->SiS_LCD1280x960Data      = SiS_LCD1280x960Data;
    SiS_Pr->SiS_StLCD1400x1050Data   = SiS_StLCD1400x1050Data;
    SiS_Pr->SiS_ExtLCD1400x1050Data  = SiS_ExtLCD1400x1050Data;
@@ -145,67 +131,30 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    SiS_Pr->SiS_ExtLCD1600x1200Data  = SiS_ExtLCD1600x1200Data;
    SiS_Pr->SiS_NoScaleData          = SiS_NoScaleData;
 
-   SiS_Pr->SiS_LVDS320x480Data_1   = SiS_LVDS320x480Data_1;
+   SiS_Pr->SiS_LVDS320x240Data_1   = SiS_LVDS320x240Data_1;
+   SiS_Pr->SiS_LVDS320x240Data_2   = SiS_LVDS320x240Data_2;
+   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
    SiS_Pr->SiS_LVDS800x600Data_1   = SiS_LVDS800x600Data_1;
-   SiS_Pr->SiS_LVDS800x600Data_2   = SiS_LVDS800x600Data_2;
-   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
-   SiS_Pr->SiS_LVDS1024x768Data_2  = SiS_LVDS1024x768Data_2;
-   SiS_Pr->SiS_LVDS1280x1024Data_1 = SiS_LVDS1280x1024Data_1;
-   SiS_Pr->SiS_LVDS1280x1024Data_2 = SiS_LVDS1280x1024Data_2;
-   SiS_Pr->SiS_LVDS1400x1050Data_1 = SiS_LVDS1400x1050Data_1;
-   SiS_Pr->SiS_LVDS1400x1050Data_2 = SiS_LVDS1400x1050Data_2;
-   SiS_Pr->SiS_LVDS1600x1200Data_1 = SiS_LVDS1600x1200Data_1;
-   SiS_Pr->SiS_LVDS1600x1200Data_2 = SiS_LVDS1600x1200Data_2;
-   SiS_Pr->SiS_LVDS1280x768Data_1  = SiS_LVDS1280x768Data_1;
-   SiS_Pr->SiS_LVDS1280x768Data_2  = SiS_LVDS1280x768Data_2;
    SiS_Pr->SiS_LVDS1024x600Data_1  = SiS_LVDS1024x600Data_1;
-   SiS_Pr->SiS_LVDS1024x600Data_2  = SiS_LVDS1024x600Data_2;
-   SiS_Pr->SiS_LVDS1152x768Data_1  = SiS_LVDS1152x768Data_1;
-   SiS_Pr->SiS_LVDS1152x768Data_2  = SiS_LVDS1152x768Data_2;
-   SiS_Pr->SiS_LVDSXXXxXXXData_1   = SiS_LVDSXXXxXXXData_1;
-   SiS_Pr->SiS_LVDS1280x960Data_1  = SiS_LVDS1280x960Data_1;
-   SiS_Pr->SiS_LVDS1280x960Data_2  = SiS_LVDS1280x960Data_2;
-   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
-   SiS_Pr->SiS_LVDS1280x960Data_1  = SiS_LVDS1280x1024Data_1;
-   SiS_Pr->SiS_LVDS1280x960Data_2  = SiS_LVDS1280x1024Data_2;
-   SiS_Pr->SiS_LVDS640x480Data_1   = SiS_LVDS640x480Data_1;
-   SiS_Pr->SiS_LVDS640x480Data_2   = SiS_LVDS640x480Data_2;
-
-   SiS_Pr->SiS_LVDS848x480Data_1   = SiS_LVDS848x480Data_1;
-   SiS_Pr->SiS_LVDS848x480Data_2   = SiS_LVDS848x480Data_2;
-   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS_LVDSBARCO1024Data_1;
-   SiS_Pr->SiS_LVDSBARCO1024Data_2 = SiS_LVDSBARCO1024Data_2;
-   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS_LVDSBARCO1366Data_1;
-   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS_LVDSBARCO1366Data_2;
+   SiS_Pr->SiS_LVDS1024x768Data_1  = SiS_LVDS1024x768Data_1;
 
-   SiS_Pr->SiS_LVDSCRT11280x768_1    = SiS_LVDSCRT11280x768_1;
+   SiS_Pr->SiS_LVDSCRT1320x240_1     = SiS_LVDSCRT1320x240_1;
+   SiS_Pr->SiS_LVDSCRT1320x240_2     = SiS_LVDSCRT1320x240_2;
+   SiS_Pr->SiS_LVDSCRT1320x240_2_H   = SiS_LVDSCRT1320x240_2_H;
+   SiS_Pr->SiS_LVDSCRT1320x240_3     = SiS_LVDSCRT1320x240_3;
+   SiS_Pr->SiS_LVDSCRT1320x240_3_H   = SiS_LVDSCRT1320x240_3_H;
+   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
+   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
+#if 0
    SiS_Pr->SiS_LVDSCRT11024x600_1    = SiS_LVDSCRT11024x600_1;
-   SiS_Pr->SiS_LVDSCRT11152x768_1    = SiS_LVDSCRT11152x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x768_1_H  = SiS_LVDSCRT11280x768_1_H;
    SiS_Pr->SiS_LVDSCRT11024x600_1_H  = SiS_LVDSCRT11024x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11152x768_1_H  = SiS_LVDSCRT11152x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x768_2    = SiS_LVDSCRT11280x768_2;
    SiS_Pr->SiS_LVDSCRT11024x600_2    = SiS_LVDSCRT11024x600_2;
-   SiS_Pr->SiS_LVDSCRT11152x768_2    = SiS_LVDSCRT11152x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x768_2_H  = SiS_LVDSCRT11280x768_2_H;
    SiS_Pr->SiS_LVDSCRT11024x600_2_H  = SiS_LVDSCRT11024x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11152x768_2_H  = SiS_LVDSCRT11152x768_2_H;
-   SiS_Pr->SiS_LVDSCRT1320x480_1     = SiS_LVDSCRT1320x480_1;
-   SiS_Pr->SiS_LVDSCRT1640x480_1     = SiS_LVDSCRT1640x480_1;
-   SiS_Pr->SiS_LVDSCRT1640x480_1_H   = SiS_LVDSCRT1640x480_1_H;
-   SiS_Pr->SiS_LVDSCRT1640x480_2     = SiS_LVDSCRT1640x480_2;
-   SiS_Pr->SiS_LVDSCRT1640x480_2_H   = SiS_LVDSCRT1640x480_2_H;
-   SiS_Pr->SiS_LVDSCRT1640x480_3     = SiS_LVDSCRT1640x480_3;
-   SiS_Pr->SiS_LVDSCRT1640x480_3_H   = SiS_LVDSCRT1640x480_3_H;
+#endif
 
    SiS_Pr->SiS_CHTVUNTSCData = SiS_CHTVUNTSCData;
    SiS_Pr->SiS_CHTVONTSCData = SiS_CHTVONTSCData;
 
-   SiS_Pr->SiS_CHTVUNTSCDesData = SiS_CHTVUNTSCDesData;
-   SiS_Pr->SiS_CHTVONTSCDesData = SiS_CHTVONTSCDesData;
-   SiS_Pr->SiS_CHTVUPALDesData  = SiS_CHTVUPALDesData;
-   SiS_Pr->SiS_CHTVOPALDesData  = SiS_CHTVOPALDesData;
-
    SiS_Pr->SiS_PanelMinLVDS   = Panel_800x600;    /* lowest value LVDS/LCDA */
    SiS_Pr->SiS_PanelMin301    = Panel_1024x768;   /* lowest value 301 */
 }
@@ -213,50 +162,24 @@ InitCommonPointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
 #ifdef SIS300
 static void
-InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitTo300Pointer(struct SiS_Private *SiS_Pr)
 {
-   InitCommonPointer(SiS_Pr, HwInfo);
+   InitCommonPointer(SiS_Pr);
 
-   SiS_Pr->SiS_SModeIDTable  = SiS300_SModeIDTable;
    SiS_Pr->SiS_VBModeIDTable = SiS300_VBModeIDTable;
    SiS_Pr->SiS_EModeIDTable  = SiS300_EModeIDTable;
    SiS_Pr->SiS_RefIndex      = SiS300_RefIndex;
    SiS_Pr->SiS_CRT1Table     = SiS300_CRT1Table;
-   if(HwInfo->jChipType == SIS_300) {
-      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_300; /* 300 */
+   if(SiS_Pr->ChipType == SIS_300) {
+      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_300; /* 300 */
    } else {
-      SiS_Pr->SiS_MCLKData_0    = SiS300_MCLKData_630; /* 630, 730 */
+      SiS_Pr->SiS_MCLKData_0 = SiS300_MCLKData_630; /* 630, 730 */
    }
    SiS_Pr->SiS_VCLKData      = SiS300_VCLKData;
-   SiS_Pr->SiS_VBVCLKData    = (SiS_VBVCLKDataStruct *)SiS300_VCLKData;
+   SiS_Pr->SiS_VBVCLKData    = (struct SiS_VBVCLKData *)SiS300_VCLKData;
 
    SiS_Pr->SiS_SR15  = SiS300_SR15;
 
-#ifdef LINUX_KERNEL
-   SiS_Pr->pSiS_SR07 = &SiS300_SR07;
-   SiS_Pr->SiS_CR40  = SiS300_CR40;
-   SiS_Pr->SiS_CR49  = SiS300_CR49;
-   SiS_Pr->pSiS_SR1F = &SiS300_SR1F;
-   SiS_Pr->pSiS_SR21 = &SiS300_SR21;
-   SiS_Pr->pSiS_SR22 = &SiS300_SR22;
-   SiS_Pr->pSiS_SR23 = &SiS300_SR23;
-   SiS_Pr->pSiS_SR24 = &SiS300_SR24;
-   SiS_Pr->SiS_SR25  = SiS300_SR25;
-   SiS_Pr->pSiS_SR31 = &SiS300_SR31;
-   SiS_Pr->pSiS_SR32 = &SiS300_SR32;
-   SiS_Pr->pSiS_SR33 = &SiS300_SR33;
-   SiS_Pr->pSiS_CRT2Data_1_2  = &SiS300_CRT2Data_1_2;
-   SiS_Pr->pSiS_CRT2Data_4_D  = &SiS300_CRT2Data_4_D;
-   SiS_Pr->pSiS_CRT2Data_4_E  = &SiS300_CRT2Data_4_E;
-   SiS_Pr->pSiS_CRT2Data_4_10 = &SiS300_CRT2Data_4_10;
-   SiS_Pr->pSiS_RGBSenseData    = &SiS300_RGBSenseData;
-   SiS_Pr->pSiS_VideoSenseData  = &SiS300_VideoSenseData;
-   SiS_Pr->pSiS_YCSenseData     = &SiS300_YCSenseData;
-   SiS_Pr->pSiS_RGBSenseData2   = &SiS300_RGBSenseData2;
-   SiS_Pr->pSiS_VideoSenseData2 = &SiS300_VideoSenseData2;
-   SiS_Pr->pSiS_YCSenseData2    = &SiS300_YCSenseData2;
-#endif
-
    SiS_Pr->SiS_PanelDelayTbl     = SiS300_PanelDelayTbl;
    SiS_Pr->SiS_PanelDelayTblLVDS = SiS300_PanelDelayTbl;
 
@@ -266,11 +189,8 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    SiS_Pr->SiS_St2LCD1280x1024Data  = SiS300_St2LCD1280x1024Data;
 
    SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS300_CRT2Part2_1024x768_1;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_1 = SiS300_CRT2Part2_1280x1024_1;
    SiS_Pr->SiS_CRT2Part2_1024x768_2  = SiS300_CRT2Part2_1024x768_2;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_2 = SiS300_CRT2Part2_1280x1024_2;
    SiS_Pr->SiS_CRT2Part2_1024x768_3  = SiS300_CRT2Part2_1024x768_3;
-   SiS_Pr->SiS_CRT2Part2_1280x1024_3 = SiS300_CRT2Part2_1280x1024_3;
 
    SiS_Pr->SiS_CHTVUPALData  = SiS300_CHTVUPALData;
    SiS_Pr->SiS_CHTVOPALData  = SiS300_CHTVOPALData;
@@ -280,64 +200,16 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    SiS_Pr->SiS_CHTVOPALNData = SiS300_CHTVOPALData;  /* not supported on 300 series */
    SiS_Pr->SiS_CHTVSOPALData = SiS300_CHTVSOPALData;
 
-   SiS_Pr->SiS_PanelType00_1 = SiS300_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = SiS300_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = SiS300_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = SiS300_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = SiS300_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = SiS300_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = SiS300_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = SiS300_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = SiS300_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = SiS300_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = SiS300_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = SiS300_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = SiS300_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = SiS300_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = SiS300_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = SiS300_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = SiS300_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = SiS300_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = SiS300_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = SiS300_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = SiS300_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = SiS300_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = SiS300_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = SiS300_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = SiS300_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = SiS300_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = SiS300_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = SiS300_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = SiS300_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = SiS300_PanelType0f_2;
-   SiS_Pr->SiS_PanelTypeNS_1 = SiS300_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = SiS300_PanelTypeNS_2;
-
-   if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1a;
-      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2a;
-   }
-   if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
-      SiS_Pr->SiS_PanelType04_1 = SiS300_PanelType04_1b;
-      SiS_Pr->SiS_PanelType04_2 = SiS300_PanelType04_2b;
-   }
-
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS300_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS300_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS300_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS300_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS300_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS300_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS300_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS300_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS300_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS300_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS300_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS300_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS300_LVDSCRT1XXXxXXX_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS300_LVDSCRT1XXXxXXX_1_H;
+   SiS_Pr->SiS_LVDS848x480Data_1   = SiS300_LVDS848x480Data_1;
+   SiS_Pr->SiS_LVDS848x480Data_2   = SiS300_LVDS848x480Data_2;
+   SiS_Pr->SiS_LVDSBARCO1024Data_1 = SiS300_LVDSBARCO1024Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_1 = SiS300_LVDSBARCO1366Data_1;
+   SiS_Pr->SiS_LVDSBARCO1366Data_2 = SiS300_LVDSBARCO1366Data_2;
+
+   SiS_Pr->SiS_PanelType04_1a = SiS300_PanelType04_1a;
+   SiS_Pr->SiS_PanelType04_2a = SiS300_PanelType04_2a;
+   SiS_Pr->SiS_PanelType04_1b = SiS300_PanelType04_1b;
+   SiS_Pr->SiS_PanelType04_2b = SiS300_PanelType04_2b;
 
    SiS_Pr->SiS_CHTVCRT1UNTSC = SiS300_CHTVCRT1UNTSC;
    SiS_Pr->SiS_CHTVCRT1ONTSC = SiS300_CHTVCRT1ONTSC;
@@ -367,64 +239,38 @@ InitTo300Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
 #ifdef SIS315H
 static void
-InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+InitTo310Pointer(struct SiS_Private *SiS_Pr)
 {
-   InitCommonPointer(SiS_Pr, HwInfo);
+   InitCommonPointer(SiS_Pr);
 
-   SiS_Pr->SiS_SModeIDTable  = SiS310_SModeIDTable;
    SiS_Pr->SiS_EModeIDTable  = SiS310_EModeIDTable;
-   SiS_Pr->SiS_RefIndex      = (SiS_Ext2Struct *)SiS310_RefIndex;
+   SiS_Pr->SiS_RefIndex      = SiS310_RefIndex;
    SiS_Pr->SiS_CRT1Table     = SiS310_CRT1Table;
-   if(HwInfo->jChipType >= SIS_340) {
-      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 */
-   } else if(HwInfo->jChipType >= SIS_761) {
+   if(SiS_Pr->ChipType >= SIS_340) {
+      SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_340;  /* 340 + XGI */
+   } else if(SiS_Pr->ChipType >= SIS_761) {
       SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_761;  /* 761 - preliminary */
-   } else if(HwInfo->jChipType >= SIS_760) {
+   } else if(SiS_Pr->ChipType >= SIS_760) {
       SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_760;  /* 760 */
-   } else if(HwInfo->jChipType >= SIS_661) {
+   } else if(SiS_Pr->ChipType >= SIS_661) {
       SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_660;  /* 661/741 */
-   } else if(HwInfo->jChipType == SIS_330) {
+   } else if(SiS_Pr->ChipType == SIS_330) {
       SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_330;  /* 330 */
-   } else if(HwInfo->jChipType > SIS_315PRO) {
+   } else if(SiS_Pr->ChipType > SIS_315PRO) {
       SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_650;  /* 550, 650, 740 */
    } else {
       SiS_Pr->SiS_MCLKData_0 = SiS310_MCLKData_0_315;  /* 315 */
    }
-   if(HwInfo->jChipType >= SIS_340) {
-      SiS_Pr->SiS_MCLKData_1    = SiS310_MCLKData_1_340;
+   if(SiS_Pr->ChipType >= SIS_340) {
+      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1_340;
    } else {
-      SiS_Pr->SiS_MCLKData_1    = SiS310_MCLKData_1;
+      SiS_Pr->SiS_MCLKData_1 = SiS310_MCLKData_1;
    }
    SiS_Pr->SiS_VCLKData      = SiS310_VCLKData;
    SiS_Pr->SiS_VBVCLKData    = SiS310_VBVCLKData;
 
    SiS_Pr->SiS_SR15  = SiS310_SR15;
 
-#ifdef LINUX_KERNEL
-   SiS_Pr->pSiS_SR07 = &SiS310_SR07;
-   SiS_Pr->SiS_CR40  = SiS310_CR40;
-   SiS_Pr->SiS_CR49  = SiS310_CR49;
-   SiS_Pr->pSiS_SR1F = &SiS310_SR1F;
-   SiS_Pr->pSiS_SR21 = &SiS310_SR21;
-   SiS_Pr->pSiS_SR22 = &SiS310_SR22;
-   SiS_Pr->pSiS_SR23 = &SiS310_SR23;
-   SiS_Pr->pSiS_SR24 = &SiS310_SR24;
-   SiS_Pr->SiS_SR25  = SiS310_SR25;
-   SiS_Pr->pSiS_SR31 = &SiS310_SR31;
-   SiS_Pr->pSiS_SR32 = &SiS310_SR32;
-   SiS_Pr->pSiS_SR33 = &SiS310_SR33;
-   SiS_Pr->pSiS_CRT2Data_1_2  = &SiS310_CRT2Data_1_2;
-   SiS_Pr->pSiS_CRT2Data_4_D  = &SiS310_CRT2Data_4_D;
-   SiS_Pr->pSiS_CRT2Data_4_E  = &SiS310_CRT2Data_4_E;
-   SiS_Pr->pSiS_CRT2Data_4_10 = &SiS310_CRT2Data_4_10;
-   SiS_Pr->pSiS_RGBSenseData    = &SiS310_RGBSenseData;
-   SiS_Pr->pSiS_VideoSenseData  = &SiS310_VideoSenseData;
-   SiS_Pr->pSiS_YCSenseData     = &SiS310_YCSenseData;
-   SiS_Pr->pSiS_RGBSenseData2   = &SiS310_RGBSenseData2;
-   SiS_Pr->pSiS_VideoSenseData2 = &SiS310_VideoSenseData2;
-   SiS_Pr->pSiS_YCSenseData2    = &SiS310_YCSenseData2;
-#endif
-
    SiS_Pr->SiS_PanelDelayTbl     = SiS310_PanelDelayTbl;
    SiS_Pr->SiS_PanelDelayTblLVDS = SiS310_PanelDelayTblLVDS;
 
@@ -435,41 +281,6 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
    SiS_Pr->SiS_CRT2Part2_1024x768_1  = SiS310_CRT2Part2_1024x768_1;
 
-   SiS_Pr->SiS_PanelType00_1 = SiS310_PanelType00_1;
-   SiS_Pr->SiS_PanelType01_1 = SiS310_PanelType01_1;
-   SiS_Pr->SiS_PanelType02_1 = SiS310_PanelType02_1;
-   SiS_Pr->SiS_PanelType03_1 = SiS310_PanelType03_1;
-   SiS_Pr->SiS_PanelType04_1 = SiS310_PanelType04_1;
-   SiS_Pr->SiS_PanelType05_1 = SiS310_PanelType05_1;
-   SiS_Pr->SiS_PanelType06_1 = SiS310_PanelType06_1;
-   SiS_Pr->SiS_PanelType07_1 = SiS310_PanelType07_1;
-   SiS_Pr->SiS_PanelType08_1 = SiS310_PanelType08_1;
-   SiS_Pr->SiS_PanelType09_1 = SiS310_PanelType09_1;
-   SiS_Pr->SiS_PanelType0a_1 = SiS310_PanelType0a_1;
-   SiS_Pr->SiS_PanelType0b_1 = SiS310_PanelType0b_1;
-   SiS_Pr->SiS_PanelType0c_1 = SiS310_PanelType0c_1;
-   SiS_Pr->SiS_PanelType0d_1 = SiS310_PanelType0d_1;
-   SiS_Pr->SiS_PanelType0e_1 = SiS310_PanelType0e_1;
-   SiS_Pr->SiS_PanelType0f_1 = SiS310_PanelType0f_1;
-   SiS_Pr->SiS_PanelType00_2 = SiS310_PanelType00_2;
-   SiS_Pr->SiS_PanelType01_2 = SiS310_PanelType01_2;
-   SiS_Pr->SiS_PanelType02_2 = SiS310_PanelType02_2;
-   SiS_Pr->SiS_PanelType03_2 = SiS310_PanelType03_2;
-   SiS_Pr->SiS_PanelType04_2 = SiS310_PanelType04_2;
-   SiS_Pr->SiS_PanelType05_2 = SiS310_PanelType05_2;
-   SiS_Pr->SiS_PanelType06_2 = SiS310_PanelType06_2;
-   SiS_Pr->SiS_PanelType07_2 = SiS310_PanelType07_2;
-   SiS_Pr->SiS_PanelType08_2 = SiS310_PanelType08_2;
-   SiS_Pr->SiS_PanelType09_2 = SiS310_PanelType09_2;
-   SiS_Pr->SiS_PanelType0a_2 = SiS310_PanelType0a_2;
-   SiS_Pr->SiS_PanelType0b_2 = SiS310_PanelType0b_2;
-   SiS_Pr->SiS_PanelType0c_2 = SiS310_PanelType0c_2;
-   SiS_Pr->SiS_PanelType0d_2 = SiS310_PanelType0d_2;
-   SiS_Pr->SiS_PanelType0e_2 = SiS310_PanelType0e_2;
-   SiS_Pr->SiS_PanelType0f_2 = SiS310_PanelType0f_2;
-   SiS_Pr->SiS_PanelTypeNS_1 = SiS310_PanelTypeNS_1;
-   SiS_Pr->SiS_PanelTypeNS_2 = SiS310_PanelTypeNS_2;
-
    SiS_Pr->SiS_CHTVUPALData  = SiS310_CHTVUPALData;
    SiS_Pr->SiS_CHTVOPALData  = SiS310_CHTVOPALData;
    SiS_Pr->SiS_CHTVUPALMData = SiS310_CHTVUPALMData;
@@ -478,33 +289,11 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    SiS_Pr->SiS_CHTVOPALNData = SiS310_CHTVOPALNData;
    SiS_Pr->SiS_CHTVSOPALData = SiS310_CHTVSOPALData;
 
-   SiS_Pr->SiS_LVDSCRT1800x600_1     = SiS310_LVDSCRT1800x600_1;
-   SiS_Pr->SiS_LVDSCRT11024x768_1    = SiS310_LVDSCRT11024x768_1;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1   = SiS310_LVDSCRT11280x1024_1;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1   = SiS310_LVDSCRT11400x1050_1;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1   = SiS310_LVDSCRT11600x1200_1;
-   SiS_Pr->SiS_LVDSCRT1800x600_1_H   = SiS310_LVDSCRT1800x600_1_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_1_H  = SiS310_LVDSCRT11024x768_1_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_1_H = SiS310_LVDSCRT11280x1024_1_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_1_H = SiS310_LVDSCRT11400x1050_1_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_1_H = SiS310_LVDSCRT11600x1200_1_H;
-   SiS_Pr->SiS_LVDSCRT1800x600_2     = SiS310_LVDSCRT1800x600_2;
-   SiS_Pr->SiS_LVDSCRT11024x768_2    = SiS310_LVDSCRT11024x768_2;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2   = SiS310_LVDSCRT11280x1024_2;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2   = SiS310_LVDSCRT11400x1050_2;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2   = SiS310_LVDSCRT11600x1200_2;
-   SiS_Pr->SiS_LVDSCRT1800x600_2_H   = SiS310_LVDSCRT1800x600_2_H;
-   SiS_Pr->SiS_LVDSCRT11024x768_2_H  = SiS310_LVDSCRT11024x768_2_H;
-   SiS_Pr->SiS_LVDSCRT11280x1024_2_H = SiS310_LVDSCRT11280x1024_2_H;
-   SiS_Pr->SiS_LVDSCRT11400x1050_2_H = SiS310_LVDSCRT11400x1050_2_H;
-   SiS_Pr->SiS_LVDSCRT11600x1200_2_H = SiS310_LVDSCRT11600x1200_2_H;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1     = SiS310_LVDSCRT1XXXxXXX_1;
-   SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H   = SiS310_LVDSCRT1XXXxXXX_1_H;
-   SiS_Pr->SiS_CHTVCRT1UNTSC         = SiS310_CHTVCRT1UNTSC;
-   SiS_Pr->SiS_CHTVCRT1ONTSC         = SiS310_CHTVCRT1ONTSC;
-   SiS_Pr->SiS_CHTVCRT1UPAL          = SiS310_CHTVCRT1UPAL;
-   SiS_Pr->SiS_CHTVCRT1OPAL          = SiS310_CHTVCRT1OPAL;
-   SiS_Pr->SiS_CHTVCRT1SOPAL         = SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1UNTSC = SiS310_CHTVCRT1UNTSC;
+   SiS_Pr->SiS_CHTVCRT1ONTSC = SiS310_CHTVCRT1ONTSC;
+   SiS_Pr->SiS_CHTVCRT1UPAL  = SiS310_CHTVCRT1UPAL;
+   SiS_Pr->SiS_CHTVCRT1OPAL  = SiS310_CHTVCRT1OPAL;
+   SiS_Pr->SiS_CHTVCRT1SOPAL = SiS310_CHTVCRT1OPAL;
 
    SiS_Pr->SiS_CHTVReg_UNTSC = SiS310_CHTVReg_UNTSC;
    SiS_Pr->SiS_CHTVReg_ONTSC = SiS310_CHTVReg_ONTSC;
@@ -528,208 +317,203 @@ InitTo310Pointer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 }
 #endif
 
-static void
-SiSInitPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+BOOLEAN
+SiSInitPtr(struct SiS_Private *SiS_Pr)
 {
-   switch(HwInfo->jChipType) {
-#ifdef SIS315H
-   case SIS_315H:
-   case SIS_315:
-   case SIS_315PRO:
-   case SIS_550:
-   case SIS_650:
-   case SIS_740:
-   case SIS_330:
-   case SIS_661:
-   case SIS_741:
-   case SIS_660:
-   case SIS_760:
-   case SIS_761:
-   case SIS_340:
-      InitTo310Pointer(SiS_Pr, HwInfo);
-      break;
-#endif
+   if(SiS_Pr->ChipType < SIS_315H) {
 #ifdef SIS300
-   case SIS_300:
-   case SIS_540:
-   case SIS_630:
-   case SIS_730:
-      InitTo300Pointer(SiS_Pr, HwInfo);
-      break;
+      InitTo300Pointer(SiS_Pr);
+#else
+      return FALSE;
+#endif
+   } else {
+#ifdef SIS315H
+      InitTo310Pointer(SiS_Pr);
+#else
+      return FALSE;
 #endif
-   default:
-      break;
    }
+   return TRUE;
 }
 
 /*********************************************/
 /*            HELPER: Get ModeID             */
 /*********************************************/
 
-#ifdef LINUX_XF86
-USHORT
-SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
-              int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+               int Depth, BOOLEAN FSTN, int LCDwidth, int LCDheight)
 {
-   USHORT ModeIndex = 0;
+   unsigned short ModeIndex = 0;
 
    switch(HDisplay)
    {
-     case 320:
-         if(VDisplay == 200)     ModeIndex = ModeIndex_320x200[Depth];
-         else if(VDisplay == 240) {
-            if(FSTN) ModeIndex = ModeIndex_320x240_FSTN[Depth];
-            else     ModeIndex = ModeIndex_320x240[Depth];
-          }
-          break;
-     case 400:
-          if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
-             if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-         }
-          break;
-     case 512:
-          if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
-             if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
-         }
-          break;
-     case 640:
-          if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
-         else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
-          break;
-     case 720:
-          if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-          else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-          break;
-     case 768:
-          if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-         break;
-     case 800:
-         if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
-         else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-          break;
-     case 848:
-         if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-         break;
-     case 856:
-         if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-         break;
-     case 960:
-         if(VGAEngine == SIS_315_VGA) {
-            if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
-            else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
-         }
-         break;
-     case 1024:
-          if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
-          else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-         else if(VGAEngine == SIS_300_VGA) {
-            if(VDisplay == 600)   ModeIndex = ModeIndex_1024x600[Depth];
-         }
-          break;
-     case 1152:
-          if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
-          if(VGAEngine == SIS_300_VGA) {
-            if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
-         }
-         break;
-     case 1280:
-          switch(VDisplay) {
-         case 720:
-            ModeIndex = ModeIndex_1280x720[Depth];
-            break;
-         case 768:
-            if(VGAEngine == SIS_300_VGA) {
-               ModeIndex = ModeIndex_300_1280x768[Depth];
-            } else {
-               ModeIndex = ModeIndex_310_1280x768[Depth];
-            }
-            break;
-         case 800:
-            if(VGAEngine == SIS_315_VGA) {
-               ModeIndex = ModeIndex_1280x800[Depth];
-            }
-            break;
-         case 960:
-            ModeIndex = ModeIndex_1280x960[Depth];
-            break;
-         case 1024:
-            ModeIndex = ModeIndex_1280x1024[Depth];
-            break;
-         }
-          break;
-     case 1360:
-          if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
-         if(VGAEngine == SIS_300_VGA) {
-            if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
-          }
-          break;
-     case 1400:
-          if(VGAEngine == SIS_315_VGA) {
-            if(VDisplay == 1050) {
-               ModeIndex = ModeIndex_1400x1050[Depth];
-            }
-         }
-          break;
-     case 1600:
-          if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
-          break;
-     case 1680:
-          if(VGAEngine == SIS_315_VGA) {
-             if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
-         }
-          break;
-     case 1920:
-          if(VDisplay == 1440)    ModeIndex = ModeIndex_1920x1440[Depth];
-         else if(VGAEngine == SIS_315_VGA) {
-            if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
-         }
-          break;
-     case 2048:
-          if(VDisplay == 1536) {
-             if(VGAEngine == SIS_300_VGA) {
-                ModeIndex = ModeIndex_300_2048x1536[Depth];
-            } else {
-                ModeIndex = ModeIndex_310_2048x1536[Depth];
-             }
-         }
-          break;
+       case 320:
+               if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
+               else if(VDisplay == 240) {
+                       if((VBFlags & CRT2_LCD) && (FSTN))
+                               ModeIndex = ModeIndex_320x240_FSTN[Depth];
+                       else
+                               ModeIndex = ModeIndex_320x240[Depth];
+               }
+               break;
+       case 400:
+               if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 800) && (LCDwidth >= 600))) {
+                       if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+               }
+               break;
+       case 512:
+               if((!(VBFlags & CRT1_LCDA)) || ((LCDwidth >= 1024) && (LCDwidth >= 768))) {
+                       if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+               }
+               break;
+       case 640:
+               if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
+               else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
+               break;
+       case 720:
+               if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+               else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+               break;
+       case 768:
+               if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+               break;
+       case 800:
+               if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
+               else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+               break;
+       case 848:
+               if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+               break;
+       case 856:
+               if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+               break;
+       case 960:
+               if(VGAEngine == SIS_315_VGA) {
+                       if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
+                       else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
+               }
+               break;
+       case 1024:
+               if(VDisplay == 576)      ModeIndex = ModeIndex_1024x576[Depth];
+               else if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+               else if(VGAEngine == SIS_300_VGA) {
+                       if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
+               }
+               break;
+       case 1152:
+               if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+               if(VGAEngine == SIS_300_VGA) {
+                       if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
+               }
+               break;
+       case 1280:
+               switch(VDisplay) {
+                       case 720:
+                               ModeIndex = ModeIndex_1280x720[Depth];
+                               break;
+                       case 768:
+                               if(VGAEngine == SIS_300_VGA) {
+                                       ModeIndex = ModeIndex_300_1280x768[Depth];
+                               } else {
+                                       ModeIndex = ModeIndex_310_1280x768[Depth];
+                               }
+                               break;
+                       case 800:
+                               if(VGAEngine == SIS_315_VGA) {
+                                       ModeIndex = ModeIndex_1280x800[Depth];
+                               }
+                               break;
+                       case 854:
+                               if(VGAEngine == SIS_315_VGA) {
+                                       ModeIndex = ModeIndex_1280x854[Depth];
+                               }
+                               break;
+                       case 960:
+                               ModeIndex = ModeIndex_1280x960[Depth];
+                               break;
+                       case 1024:
+                               ModeIndex = ModeIndex_1280x1024[Depth];
+                               break;
+               }
+               break;
+       case 1360:
+               if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+               if(VGAEngine == SIS_300_VGA) {
+                       if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
+               }
+               break;
+       case 1400:
+               if(VGAEngine == SIS_315_VGA) {
+                       if(VDisplay == 1050) {
+                               ModeIndex = ModeIndex_1400x1050[Depth];
+                       }
+               }
+               break;
+       case 1600:
+               if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+               break;
+       case 1680:
+               if(VGAEngine == SIS_315_VGA) {
+                       if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+               }
+               break;
+       case 1920:
+               if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+               else if(VGAEngine == SIS_315_VGA) {
+                       if(VDisplay == 1080) ModeIndex = ModeIndex_1920x1080[Depth];
+               }
+               break;
+       case 2048:
+               if(VDisplay == 1536) {
+                       if(VGAEngine == SIS_300_VGA) {
+                               ModeIndex = ModeIndex_300_2048x1536[Depth];
+                       } else {
+                               ModeIndex = ModeIndex_310_2048x1536[Depth];
+                       }
+               }
+               break;
    }
 
-   return(ModeIndex);
+   return ModeIndex;
 }
-#endif
 
-USHORT
-SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
-                  int Depth, BOOLEAN FSTN, USHORT CustomT, int LCDwidth, int LCDheight)
+unsigned short
+SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+               int Depth, BOOLEAN FSTN, unsigned short CustomT, int LCDwidth, int LCDheight,
+               unsigned int VBFlags2)
 {
-   USHORT ModeIndex = 0;
+   unsigned short ModeIndex = 0;
 
-   if(VBFlags & (VB_LVDS | VB_30xBDH)) {
+   if(VBFlags2 & (VB2_LVDS | VB2_30xBDH)) {
 
       switch(HDisplay)
       {
        case 320:
-            if(CustomT != CUT_PANEL848) {
-               if(VDisplay == 200) ModeIndex = ModeIndex_320x200[Depth];
-               else if(VDisplay == 240) {
+            if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+               if(VDisplay == 200) {
+                  if(!FSTN) ModeIndex = ModeIndex_320x200[Depth];
+               } else if(VDisplay == 240) {
                   if(!FSTN) ModeIndex = ModeIndex_320x240[Depth];
-                  else if(VGAEngine == SIS_315_VGA) {
-                      ModeIndex = ModeIndex_320x240_FSTN[Depth];
+                  else if(VGAEngine == SIS_315_VGA) {
+                     ModeIndex = ModeIndex_320x240_FSTN[Depth];
                   }
                }
             }
-             break;
-       case 400:
-            if(CustomT != CUT_PANEL848) {
-               if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
-                  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+            break;
+       case 400:
+            if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+               if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
+                  if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
                }
             }
-             break;
+            break;
        case 512:
-            if(CustomT != CUT_PANEL848) {
-               if(!((VGAEngine == SIS_300_VGA) && (VBFlags & VB_TRUMPION))) {
+            if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856)) {
+               if(!((VGAEngine == SIS_300_VGA) && (VBFlags2 & VB2_TRUMPION))) {
                   if(LCDwidth >= 1024 && LCDwidth != 1152 && LCDheight >= 768) {
                      if(VDisplay == 384) {
                         ModeIndex = ModeIndex_512x384[Depth];
@@ -739,9 +523,10 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
             }
             break;
        case 640:
-            if(VDisplay == 480)            ModeIndex = ModeIndex_640x480[Depth];
+            if(VDisplay == 480) ModeIndex = ModeIndex_640x480[Depth];
             else if(VDisplay == 400) {
-               if(CustomT != CUT_PANEL848) ModeIndex = ModeIndex_640x400[Depth];
+               if((CustomT != CUT_PANEL848) && (CustomT != CUT_PANEL856))
+                  ModeIndex = ModeIndex_640x400[Depth];
             }
             break;
        case 800:
@@ -752,6 +537,11 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
                if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
             }
             break;
+       case 856:
+            if(CustomT == CUT_PANEL856) {
+               if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+            }
+            break;
        case 1024:
             if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
             else if(VGAEngine == SIS_300_VGA) {
@@ -762,7 +552,7 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
             break;
        case 1152:
             if(VGAEngine == SIS_300_VGA) {
-               if((VDisplay == 768) && (LCDheight == 768)) {
+               if((VDisplay == 768) && (LCDheight == 768)) {
                   ModeIndex = ModeIndex_1152x768[Depth];
                }
             }
@@ -770,49 +560,49 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
         case 1280:
             if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
             else if(VGAEngine == SIS_315_VGA) {
-               if((VDisplay == 768) && (LCDheight == 768)) {
+               if((VDisplay == 768) && (LCDheight == 768)) {
                   ModeIndex = ModeIndex_310_1280x768[Depth];
                }
             }
             break;
        case 1360:
             if(VGAEngine == SIS_300_VGA) {
-               if(CustomT == CUT_BARCO1366) {
+               if(CustomT == CUT_BARCO1366) {
                   if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
                }
             }
             if(CustomT == CUT_PANEL848) {
-               if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+               if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
             }
             break;
        case 1400:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
+               if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
             }
             break;
        case 1600:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+               if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
             }
             break;
       }
 
-   } else if(VBFlags & VB_SISBRIDGE) {
+   } else if(VBFlags2 & VB2_SISBRIDGE) {
 
       switch(HDisplay)
       {
        case 320:
-            if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
+            if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
             else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
-             break;
-       case 400:
+            break;
+       case 400:
             if(LCDwidth >= 800 && LCDheight >= 600) {
-                if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+               if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
             }
-             break;
+            break;
        case 512:
             if(LCDwidth >= 1024 && LCDheight >= 768 && LCDwidth != 1152) {
-               if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+               if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
             }
             break;
        case 640:
@@ -821,96 +611,115 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
             break;
        case 720:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+               if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
                else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
             }
             break;
        case 768:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+               if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
             }
             break;
        case 800:
             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+               if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
             }
             break;
        case 848:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+               if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
             }
             break;
        case 856:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+               if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
             }
             break;
        case 960:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
+               if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
                else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
             }
             break;
        case 1024:
             if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+               if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
             }
             break;
        case 1152:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+               if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
             }
             break;
        case 1280:
             switch(VDisplay) {
             case 720:
-               ModeIndex = ModeIndex_1280x720[Depth];
+               ModeIndex = ModeIndex_1280x720[Depth];
             case 768:
-               if(VGAEngine == SIS_300_VGA) {
+               if(VGAEngine == SIS_300_VGA) {
                   ModeIndex = ModeIndex_300_1280x768[Depth];
                } else {
                   ModeIndex = ModeIndex_310_1280x768[Depth];
                }
                break;
             case 800:
-               if(VGAEngine == SIS_315_VGA) {
+               if(VGAEngine == SIS_315_VGA) {
                   ModeIndex = ModeIndex_1280x800[Depth];
                }
                break;
+            case 854:
+               if(VGAEngine == SIS_315_VGA) {
+                  ModeIndex = ModeIndex_1280x854[Depth];
+               }
+               break;
             case 960:
-               ModeIndex = ModeIndex_1280x960[Depth];
+               ModeIndex = ModeIndex_1280x960[Depth];
                break;
             case 1024:
-               ModeIndex = ModeIndex_1280x1024[Depth];
+               ModeIndex = ModeIndex_1280x1024[Depth];
                break;
             }
             break;
        case 1360:
-            if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+            if(VGAEngine == SIS_315_VGA) {  /* OVER1280 only? */
+               if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
             }
             break;
        case 1400:
             if(VGAEngine == SIS_315_VGA) {
-               if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
+               if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
                   if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
                }
             }
             break;
        case 1600:
             if(VGAEngine == SIS_315_VGA) {
-               if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
-                  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
+               if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+                  if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
                }
             }
             break;
 #ifndef VB_FORBID_CRT2LCD_OVER_1600
        case 1680:
             if(VGAEngine == SIS_315_VGA) {
-               if(VBFlags & (VB_301C | VB_302LV | VB_302ELV)) {
-                  if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+               if(VBFlags2 & VB2_LCDOVER1280BRIDGE) {
+                  if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
+               }
+            }
+            break;
+       case 1920:
+            if(VGAEngine == SIS_315_VGA) {
+               if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+                  if(VDisplay == 1440) ModeIndex = ModeIndex_1920x1440[Depth];
+               }
+            }
+            break;
+       case 2048:
+            if(VGAEngine == SIS_315_VGA) {
+               if(VBFlags2 & VB2_LCDOVER1600BRIDGE) {
+                  if(VDisplay == 1536) ModeIndex = ModeIndex_310_2048x1536[Depth];
                }
             }
             break;
@@ -921,16 +730,17 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
    return ModeIndex;
 }
 
-USHORT
-SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth)
+unsigned short
+SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+                       unsigned int VBFlags2)
 {
-   USHORT ModeIndex = 0;
+   unsigned short ModeIndex = 0;
 
-   if(VBFlags & VB_CHRONTEL) {
+   if(VBFlags2 & VB2_CHRONTEL) {
 
       switch(HDisplay)
       {
-       case 512:
+       case 512:
             if(VGAEngine == SIS_315_VGA) {
                if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
             }
@@ -944,27 +754,27 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
             break;
        case 1024:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+               if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
             }
             break;
       }
 
-   } else if(VBFlags & VB_SISTVBRIDGE) {
+   } else if(VBFlags2 & VB2_SISTVBRIDGE) {
 
       switch(HDisplay)
       {
        case 320:
-            if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
+            if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
             else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
-             break;
-        case 400:
-             if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-             break;
-       case 512:
+            break;
+       case 400:
+            if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
+            break;
+       case 512:
             if( ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR750P | TV_YPBPR1080I))) ||
-                (VBFlags & TV_HIVISION)                                              ||
-                ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
-               if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
+                (VBFlags & TV_HIVISION)                                              ||
+                ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
+               if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
             }
             break;
        case 640:
@@ -973,34 +783,34 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
             break;
        case 720:
             if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
-                if(VDisplay == 480) {
-                   ModeIndex = ModeIndex_720x480[Depth];
-                } else if(VDisplay == 576) {
+               if(VDisplay == 480) {
+                  ModeIndex = ModeIndex_720x480[Depth];
+               } else if(VDisplay == 576) {
                   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
                       ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) )
-                      ModeIndex = ModeIndex_720x576[Depth];
-                }
+                     ModeIndex = ModeIndex_720x576[Depth];
+               }
             }
              break;
        case 768:
             if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
-               if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
+               if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
                    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL)) ) {
-                  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+                  if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
                }
              }
             break;
        case 800:
             if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
             else if(VDisplay == 480) {
-               if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+               if(!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P))) {
                   ModeIndex = ModeIndex_800x480[Depth];
                }
             }
             break;
        case 960:
             if(VGAEngine == SIS_315_VGA) {
-               if(VDisplay == 600) {
+               if(VDisplay == 600) {
                   if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
                      ModeIndex = ModeIndex_960x600[Depth];
                   }
@@ -1009,25 +819,28 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
             break;
        case 1024:
             if(VDisplay == 768) {
-               if(VBFlags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)) {
+               if(VBFlags2 & VB2_30xBLV) {
                   ModeIndex = ModeIndex_1024x768[Depth];
                }
             } else if(VDisplay == 576) {
-               if((VBFlags & TV_HIVISION) || ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
+               if( (VBFlags & TV_HIVISION) ||
+                   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)) ||
+                   ((VBFlags2 & VB2_30xBLV) &&
+                    ((!(VBFlags & (TV_YPBPR | TV_PALM))) && (VBFlags & TV_PAL))) ) {
                   ModeIndex = ModeIndex_1024x576[Depth];
                }
             }
             break;
        case 1280:
             if(VDisplay == 720) {
-               if((VBFlags & TV_HIVISION) ||
+               if((VBFlags & TV_HIVISION) ||
                   ((VBFlags & TV_YPBPR) && (VBFlags & (TV_YPBPR1080I | TV_YPBPR750P)))) {
-                  ModeIndex = ModeIndex_1280x720[Depth];
+                  ModeIndex = ModeIndex_1280x720[Depth];
                }
             } else if(VDisplay == 1024) {
-               if((VBFlags & TV_HIVISION) ||
+               if((VBFlags & TV_HIVISION) ||
                   ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I))) {
-                  ModeIndex = ModeIndex_1280x1024[Depth];
+                  ModeIndex = ModeIndex_1280x1024[Depth];
                }
             }
             break;
@@ -1036,99 +849,31 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int D
    return ModeIndex;
 }
 
-USHORT
-SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth)
+unsigned short
+SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay, int Depth,
+                       unsigned int VBFlags2)
 {
-   USHORT ModeIndex = 0;
+   if(!(VBFlags2 & VB2_SISVGA2BRIDGE)) return 0;
 
-   if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
+   if(HDisplay >= 1920) return 0;
 
    switch(HDisplay)
    {
-       case 320:
-               if(VDisplay == 200)      ModeIndex = ModeIndex_320x200[Depth];
-               else if(VDisplay == 240) ModeIndex = ModeIndex_320x240[Depth];
-               break;
-       case 400:
-               if(VDisplay == 300) ModeIndex = ModeIndex_400x300[Depth];
-               break;
-       case 512:
-               if(VDisplay == 384) ModeIndex = ModeIndex_512x384[Depth];
-               break;
-       case 640:
-               if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
-               else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
-               break;
-       case 720:
-               if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-               else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-               break;
-       case 768:
-               if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-               break;
-       case 800:
-               if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
-               else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-               break;
-       case 848:
-               if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-               break;
-       case 856:
-               if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-               break;
-       case 960:
-               if(VGAEngine == SIS_315_VGA) {
-                  if(VDisplay == 540)      ModeIndex = ModeIndex_960x540[Depth];
-                  else if(VDisplay == 600) ModeIndex = ModeIndex_960x600[Depth];
-               }
-               break;
-       case 1024:
-               if(VDisplay == 768)      ModeIndex = ModeIndex_1024x768[Depth];
-               else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
-               break;
-       case 1152:
-               if(VDisplay == 864)    ModeIndex = ModeIndex_1152x864[Depth];
-               else if(VGAEngine == SIS_300_VGA) {
-                  if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
-               }
-               break;
-       case 1280:
-               if(VDisplay == 768) {
-                  if(VGAEngine == SIS_300_VGA) {
-                     ModeIndex = ModeIndex_300_1280x768[Depth];
-                  } else {
-                     ModeIndex = ModeIndex_310_1280x768[Depth];
-                  }
-               } else if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
-               else if(VDisplay == 720)    ModeIndex = ModeIndex_1280x720[Depth];
-               else if(VDisplay == 800)    ModeIndex = ModeIndex_1280x800[Depth];
-               else if(VDisplay == 960)    ModeIndex = ModeIndex_1280x960[Depth];
-               break;
-        case 1360:
-               if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
-                break;
-        case 1400:
-               if(VGAEngine == SIS_315_VGA) {
-                  if(VDisplay == 1050) ModeIndex = ModeIndex_1400x1050[Depth];
-               }
-               break;
        case 1600:
-               if(VGAEngine == SIS_315_VGA) {
-                  if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
-                     if(VDisplay == 1200) ModeIndex = ModeIndex_1600x1200[Depth];
-                  }
+               if(VDisplay == 1200) {
+                       if(VGAEngine != SIS_315_VGA) return 0;
+                       if(!(VBFlags2 & VB2_30xB)) return 0;
                }
                break;
        case 1680:
-               if(VGAEngine == SIS_315_VGA) {
-                  if(VBFlags & (VB_301B|VB_301C|VB_302B)) {
-                     if(VDisplay == 1050) ModeIndex = ModeIndex_1680x1050[Depth];
-                  }
+               if(VDisplay == 1050) {
+                       if(VGAEngine != SIS_315_VGA) return 0;
+                       if(!(VBFlags2 & VB2_30xB)) return 0;
                }
                break;
    }
 
-   return ModeIndex;
+   return SiS_GetModeID(VGAEngine, 0, HDisplay, VDisplay, Depth, FALSE, 0, 0);
 }
 
 
@@ -1137,83 +882,83 @@ SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int
 /*********************************************/
 
 void
-SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data)
+SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data)
 {
-   OutPortByte(port,index);
-   OutPortByte(port + 1,data);
+   OutPortByte(port, index);
+   OutPortByte(port + 1, data);
 }
 
 void
-SiS_SetRegByte(SISIOADDRESS port, USHORT data)
+SiS_SetRegByte(SISIOADDRESS port, unsigned short data)
 {
-   OutPortByte(port,data);
+   OutPortByte(port, data);
 }
 
 void
-SiS_SetRegShort(SISIOADDRESS port, USHORT data)
+SiS_SetRegShort(SISIOADDRESS port, unsigned short data)
 {
-   OutPortWord(port,data);
+   OutPortWord(port, data);
 }
 
 void
-SiS_SetRegLong(SISIOADDRESS port, ULONG data)
+SiS_SetRegLong(SISIOADDRESS port, unsigned int data)
 {
-   OutPortLong(port,data);
+   OutPortLong(port, data);
 }
 
-UCHAR
-SiS_GetReg(SISIOADDRESS port, USHORT index)
+unsigned char
+SiS_GetReg(SISIOADDRESS port, unsigned short index)
 {
-   OutPortByte(port,index);
+   OutPortByte(port, index);
    return(InPortByte(port + 1));
 }
 
-UCHAR
+unsigned char
 SiS_GetRegByte(SISIOADDRESS port)
 {
    return(InPortByte(port));
 }
 
-USHORT
+unsigned short
 SiS_GetRegShort(SISIOADDRESS port)
 {
    return(InPortWord(port));
 }
 
-ULONG
+unsigned int
 SiS_GetRegLong(SISIOADDRESS port)
 {
    return(InPortLong(port));
 }
 
 void
-SiS_SetRegANDOR(SISIOADDRESS Port,USHORT Index,USHORT DataAND,USHORT DataOR)
+SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND, unsigned short DataOR)
 {
-  USHORT temp;
+   unsigned short temp;
 
-  temp = SiS_GetReg(Port,Index);
-  temp = (temp & (DataAND)) | DataOR;
-  SiS_SetReg(Port,Index,temp);
+   temp = SiS_GetReg(Port, Index);
+   temp = (temp & (DataAND)) | DataOR;
+   SiS_SetReg(Port, Index, temp);
 }
 
 void
-SiS_SetRegAND(SISIOADDRESS Port,USHORT Index,USHORT DataAND)
+SiS_SetRegAND(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND)
 {
-  USHORT temp;
+   unsigned short temp;
 
-  temp = SiS_GetReg(Port,Index);
-  temp &= DataAND;
-  SiS_SetReg(Port,Index,temp);
+   temp = SiS_GetReg(Port, Index);
+   temp &= DataAND;
+   SiS_SetReg(Port, Index, temp);
 }
 
 void
-SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR)
+SiS_SetRegOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataOR)
 {
-  USHORT temp;
+   unsigned short temp;
 
-  temp = SiS_GetReg(Port,Index);
-  temp |= DataOR;
-  SiS_SetReg(Port,Index,temp);
+   temp = SiS_GetReg(Port, Index);
+   temp |= DataOR;
+   SiS_SetReg(Port, Index, temp);
 }
 
 /*********************************************/
@@ -1221,13 +966,13 @@ SiS_SetRegOR(SISIOADDRESS Port,USHORT Index,USHORT DataOR)
 /*********************************************/
 
 void
-SiS_DisplayOn(SiS_Private *SiS_Pr)
+SiS_DisplayOn(struct SiS_Private *SiS_Pr)
 {
    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x01,0xDF);
 }
 
 void
-SiS_DisplayOff(SiS_Private *SiS_Pr)
+SiS_DisplayOff(struct SiS_Private *SiS_Pr)
 {
    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x20);
 }
@@ -1238,7 +983,7 @@ SiS_DisplayOff(SiS_Private *SiS_Pr)
 /*********************************************/
 
 void
-SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
+SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
 {
    SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
    SiS_Pr->SiS_P3d4 = BaseAddr + 0x24;
@@ -1251,16 +996,17 @@ SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
    SiS_Pr->SiS_P3c8 = BaseAddr + 0x18;
    SiS_Pr->SiS_P3c9 = BaseAddr + 0x19;
    SiS_Pr->SiS_P3cb = BaseAddr + 0x1b;
+   SiS_Pr->SiS_P3cc = BaseAddr + 0x1c;
    SiS_Pr->SiS_P3cd = BaseAddr + 0x1d;
    SiS_Pr->SiS_P3da = BaseAddr + 0x2a;
-   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;     /* Digital video interface registers (LCD) */
-   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;     /* 301 TV Encoder registers */
-   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;     /* 301 Macrovision registers */
-   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;     /* 301 VGA2 (and LCD) registers */
-   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2; /* 301 palette address port registers */
-   SiS_Pr->SiS_DDC_Port = BaseAddr + 0x14;                  /* DDC Port ( = P3C4, SR11/0A) */
-   SiS_Pr->SiS_VidCapt = BaseAddr + SIS_VIDEO_CAPTURE;
-   SiS_Pr->SiS_VidPlay = BaseAddr + SIS_VIDEO_PLAYBACK;
+   SiS_Pr->SiS_Part1Port = BaseAddr + SIS_CRT2_PORT_04;
+   SiS_Pr->SiS_Part2Port = BaseAddr + SIS_CRT2_PORT_10;
+   SiS_Pr->SiS_Part3Port = BaseAddr + SIS_CRT2_PORT_12;
+   SiS_Pr->SiS_Part4Port = BaseAddr + SIS_CRT2_PORT_14;
+   SiS_Pr->SiS_Part5Port = BaseAddr + SIS_CRT2_PORT_14 + 2;
+   SiS_Pr->SiS_DDC_Port  = BaseAddr + 0x14;
+   SiS_Pr->SiS_VidCapt   = BaseAddr + SIS_VIDEO_CAPTURE;
+   SiS_Pr->SiS_VidPlay   = BaseAddr + SIS_VIDEO_PLAYBACK;
 }
 
 /*********************************************/
@@ -1268,7 +1014,7 @@ SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr)
 /*********************************************/
 
 static void
-SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_GetSysFlags(struct SiS_Private *SiS_Pr)
 {
    unsigned char cr5f, temp1, temp2;
 
@@ -1276,9 +1022,9 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    /* (SR11 is used for DDC and in enable/disablebridge) */
    SiS_Pr->SiS_SensibleSR11 = FALSE;
    SiS_Pr->SiS_MyCR63 = 0x63;
-   if(HwInfo->jChipType >= SIS_330) {
+   if(SiS_Pr->ChipType >= SIS_330) {
       SiS_Pr->SiS_MyCR63 = 0x53;
-      if(HwInfo->jChipType >= SIS_661) {
+      if(SiS_Pr->ChipType >= SIS_661) {
          SiS_Pr->SiS_SensibleSR11 = TRUE;
       }
    }
@@ -1286,43 +1032,52 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    /* You should use the macros, not these flags directly */
 
    SiS_Pr->SiS_SysFlags = 0;
-   if(HwInfo->jChipType == SIS_650) {
+   if(SiS_Pr->ChipType == SIS_650) {
       cr5f = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x5c,0x07);
       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x5c,0xf8);
       temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
       if((!temp1) || (temp2)) {
-         switch(cr5f) {
+        switch(cr5f) {
            case 0x80:
            case 0x90:
            case 0xc0:
-              SiS_Pr->SiS_SysFlags |= SF_IsM650;  break;
+              SiS_Pr->SiS_SysFlags |= SF_IsM650;
+              break;
            case 0xa0:
            case 0xb0:
            case 0xe0:
-              SiS_Pr->SiS_SysFlags |= SF_Is651;   break;
+              SiS_Pr->SiS_SysFlags |= SF_Is651;
+              break;
         }
       } else {
-         switch(cr5f) {
+        switch(cr5f) {
            case 0x90:
               temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8;
               switch(temp1) {
-                 case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
+                 case 0x00: SiS_Pr->SiS_SysFlags |= SF_IsM652; break;
                  case 0x40: SiS_Pr->SiS_SysFlags |= SF_IsM653; break;
                  default:   SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
               }
               break;
            case 0xb0:
-              SiS_Pr->SiS_SysFlags |= SF_Is652;  break;
+              SiS_Pr->SiS_SysFlags |= SF_Is652;
+              break;
            default:
-              SiS_Pr->SiS_SysFlags |= SF_IsM650; break;
+              SiS_Pr->SiS_SysFlags |= SF_IsM650;
+              break;
         }
       }
    }
-   if(HwInfo->jChipType == SIS_760) {
-      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
-      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB;
+
+   if(SiS_Pr->ChipType >= SIS_760 && SiS_Pr->ChipType <= SIS_761) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x30) {
+         SiS_Pr->SiS_SysFlags |= SF_760LFB;
+      }
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0xf0) {
+         SiS_Pr->SiS_SysFlags |= SF_760UMA;
+      }
    }
 }
 
@@ -1331,18 +1086,20 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static void
-SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSInitPCIetc(struct SiS_Private *SiS_Pr)
 {
-   switch(HwInfo->jChipType) {
+   switch(SiS_Pr->ChipType) {
+#ifdef SIS300
    case SIS_300:
    case SIS_540:
    case SIS_630:
    case SIS_730:
       /* Set - PCI LINEAR ADDRESSING ENABLE (0x80)
-       *     - RELOCATED VGA IO  (0x20)
-       *     - MMIO ENABLE (0x1)
+       *     - RELOCATED VGA IO ENABLED (0x20)
+       *     - MMIO ENABLED (0x01)
+       * Leave other bits untouched.
        */
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
       /*  - Enable 2D (0x40)
        *  - Enable 3D (0x02)
        *  - Enable 3D Vertex command fetch (0x10) ?
@@ -1350,6 +1107,8 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
        */
       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x5A);
       break;
+#endif
+#ifdef SIS315H
    case SIS_315H:
    case SIS_315:
    case SIS_315PRO:
@@ -1362,21 +1121,30 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    case SIS_760:
    case SIS_761:
    case SIS_340:
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
-      /*  - Enable 2D (0x40)
-       *  - Enable 3D (0x02)
+   case XGI_40:
+      /* See above */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
+      /*  - Enable 3D G/L transformation engine (0x80)
+       *  - Enable 2D (0x40)
        *  - Enable 3D vertex command fetch (0x10)
        *  - Enable 3D command parser (0x08)
-       *  - Enable 3D G/L transformation engine (0x80)
+       *  - Enable 3D (0x02)
        */
       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0xDA);
       break;
+   case XGI_20:
    case SIS_550:
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x20,0xa1);
+      /* See above */
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x20,0xa1);
       /* No 3D engine ! */
       /*  - Enable 2D (0x40)
+       *  - disable 3D
        */
-      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x40);
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1E,0x60,0x40);
+      break;
+#endif
+   default:
+      break;
    }
 }
 
@@ -1384,38 +1152,40 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*             HELPER: SetLVDSetc            */
 /*********************************************/
 
-static void
-SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiSSetLVDSetc(struct SiS_Private *SiS_Pr)
 {
-   USHORT temp;
+   unsigned short temp;
 
    SiS_Pr->SiS_IF_DEF_LVDS = 0;
    SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
    SiS_Pr->SiS_IF_DEF_CH70xx = 0;
-   SiS_Pr->SiS_IF_DEF_DSTN = 0;
-   SiS_Pr->SiS_IF_DEF_FSTN = 0;
    SiS_Pr->SiS_IF_DEF_CONEX = 0;
 
    SiS_Pr->SiS_ChrontelInit = 0;
 
+   if(SiS_Pr->ChipType == XGI_20) return;
+
    /* Check for SiS30x first */
    temp = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
    if((temp == 1) || (temp == 2)) return;
 
-   switch(HwInfo->jChipType) {
+   switch(SiS_Pr->ChipType) {
 #ifdef SIS300
    case SIS_540:
    case SIS_630:
    case SIS_730:
-       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-       temp = (temp & 0x0E) >> 1;
-       if((temp >= 2) && (temp <= 5))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
-       if(temp == 3)                   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
-       if((temp == 4) || (temp == 5)) {
+       temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+       if((temp >= 2) && (temp <= 5))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
+       if(temp == 3)                   SiS_Pr->SiS_IF_DEF_TRUMPION = 1;
+       if((temp == 4) || (temp == 5)) {
                /* Save power status (and error check) - UNUSED */
                SiS_Pr->SiS_Backup70xx = SiS_GetCH700x(SiS_Pr, 0x0e);
                SiS_Pr->SiS_IF_DEF_CH70xx = 1;
-        }
+       }
        break;
 #endif
 #ifdef SIS315H
@@ -1423,26 +1193,26 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    case SIS_650:
    case SIS_740:
    case SIS_330:
-        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-       temp = (temp & 0x0E) >> 1;
-       if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
-       if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-        break;
+       temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x37) & 0x0e) >> 1;
+       if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
+       if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+       break;
    case SIS_661:
    case SIS_741:
    case SIS_660:
    case SIS_760:
    case SIS_761:
    case SIS_340:
-        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-       temp = (temp & 0xe0) >> 5;
-       if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
-       if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
-       if(temp == 4)                   SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
-        break;
+   case XGI_20:
+   case XGI_40:
+       temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0xe0) >> 5;
+       if((temp >= 2) && (temp <= 3))  SiS_Pr->SiS_IF_DEF_LVDS = 1;
+       if(temp == 3)                   SiS_Pr->SiS_IF_DEF_CH70xx = 2;
+       if(temp == 4)                   SiS_Pr->SiS_IF_DEF_CONEX = 1;  /* Not yet supported */
+       break;
 #endif
    default:
-        break;
+       break;
    }
 }
 
@@ -1451,35 +1221,55 @@ SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 void
-SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable)
+SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable)
 {
    SiS_Pr->SiS_IF_DEF_DSTN = enable ? 1 : 0;
 }
 
 void
-SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable)
+SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable)
 {
    SiS_Pr->SiS_IF_DEF_FSTN = enable ? 1 : 0;
 }
 
+/*********************************************/
+/*            HELPER: Get modeflag           */
+/*********************************************/
+
+unsigned short
+SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex)
+{
+   if(SiS_Pr->UseCustomMode) {
+      return SiS_Pr->CModeFlag;
+   } else if(ModeNo <= 0x13) {
+      return SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else {
+      return SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+}
+
 /*********************************************/
 /*        HELPER: Determine ROM usage        */
 /*********************************************/
 
 BOOLEAN
-SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr)
 {
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
-   USHORT romversoffs, romvmaj = 1, romvmin = 0;
-
-   if(HwInfo->jChipType >= SIS_761) {
-      /* I very much assume 761 and 340 will use new layout */
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+   unsigned short romversoffs, romvmaj = 1, romvmin = 0;
+
+   if(SiS_Pr->ChipType >= XGI_20) {
+      /* XGI ROMs don't qualify */
+      return FALSE;
+   } else if(SiS_Pr->ChipType >= SIS_761) {
+      /* I very much assume 761, 340 and newer will use new layout */
       return TRUE;
-   } else if(HwInfo->jChipType >= SIS_661) {
+   } else if(SiS_Pr->ChipType >= SIS_661) {
       if((ROMAddr[0x1a] == 'N') &&
-         (ROMAddr[0x1b] == 'e') &&
-         (ROMAddr[0x1c] == 'w') &&
-         (ROMAddr[0x1d] == 'V')) {
+        (ROMAddr[0x1b] == 'e') &&
+        (ROMAddr[0x1c] == 'w') &&
+        (ROMAddr[0x1d] == 'V')) {
         return TRUE;
       }
       romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
@@ -1494,9 +1284,9 @@ SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
       }
    } else if(IS_SIS650740) {
       if((ROMAddr[0x1a] == 'N') &&
-         (ROMAddr[0x1b] == 'e') &&
-         (ROMAddr[0x1c] == 'w') &&
-         (ROMAddr[0x1d] == 'V')) {
+        (ROMAddr[0x1b] == 'e') &&
+        (ROMAddr[0x1c] == 'w') &&
+        (ROMAddr[0x1d] == 'V')) {
         return TRUE;
       }
    }
@@ -1504,45 +1294,50 @@ SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 }
 
 static void
-SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiSDetermineROMUsage(struct SiS_Private *SiS_Pr)
 {
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
-   USHORT romptr = 0;
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+   unsigned short romptr = 0;
 
    SiS_Pr->SiS_UseROM = FALSE;
    SiS_Pr->SiS_ROMNew = FALSE;
+   SiS_Pr->SiS_PWDOffset = 0;
 
-   if((ROMAddr) && (HwInfo->UseROM)) {
-      if(HwInfo->jChipType == SIS_300) {
-         /* 300: We check if the code starts below 0x220 by
+   if(SiS_Pr->ChipType >= XGI_20) return;
+
+   if((ROMAddr) && (SiS_Pr->UseROM)) {
+      if(SiS_Pr->ChipType == SIS_300) {
+        /* 300: We check if the code starts below 0x220 by
          * checking the jmp instruction at the beginning
          * of the BIOS image.
          */
         if((ROMAddr[3] == 0xe9) && ((ROMAddr[5] << 8) | ROMAddr[4]) > 0x21a)
            SiS_Pr->SiS_UseROM = TRUE;
-      } else if(HwInfo->jChipType < SIS_315H) {
+      } else if(SiS_Pr->ChipType < SIS_315H) {
         /* Sony's VAIO BIOS 1.09 follows the standard, so perhaps
          * the others do as well
          */
         SiS_Pr->SiS_UseROM = TRUE;
       } else {
-         /* 315/330 series stick to the standard(s) */
+        /* 315/330 series stick to the standard(s) */
         SiS_Pr->SiS_UseROM = TRUE;
-        if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
+        if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr))) {
            SiS_Pr->SiS_EMIOffset = 14;
+           SiS_Pr->SiS_PWDOffset = 17;
            SiS_Pr->SiS661LCD2TableSize = 36;
            /* Find out about LCD data table entry size */
            if((romptr = SISGETROMW(0x0102))) {
               if(ROMAddr[romptr + (32 * 16)] == 0xff)
-                 SiS_Pr->SiS661LCD2TableSize = 32;
+                 SiS_Pr->SiS661LCD2TableSize = 32;
               else if(ROMAddr[romptr + (34 * 16)] == 0xff)
-                 SiS_Pr->SiS661LCD2TableSize = 34;
-              else if(ROMAddr[romptr + (36 * 16)] == 0xff)        /* 0.94 */
-                 SiS_Pr->SiS661LCD2TableSize = 36;
+                 SiS_Pr->SiS661LCD2TableSize = 34;
+              else if(ROMAddr[romptr + (36 * 16)] == 0xff)        /* 0.94, 2.05.00+ */
+                 SiS_Pr->SiS661LCD2TableSize = 36;
               else if( (ROMAddr[romptr + (38 * 16)] == 0xff) ||   /* 2.00.00 - 2.02.00 */
-                       (ROMAddr[0x6F] & 0x01) ) {                 /* 2.03.00+ */
-                 SiS_Pr->SiS661LCD2TableSize = 38;
+                       (ROMAddr[0x6F] & 0x01) ) {                 /* 2.03.00 - <2.05.00 */
+                 SiS_Pr->SiS661LCD2TableSize = 38;                /* UMC data layout abandoned at 2.05.00 */
                  SiS_Pr->SiS_EMIOffset = 16;
+                 SiS_Pr->SiS_PWDOffset = 19;
               }
            }
         }
@@ -1555,9 +1350,9 @@ SiSDetermineROMUsage(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static void
-SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegRegLower(struct SiS_Private *SiS_Pr, unsigned short value)
 {
-   USHORT temp;
+   unsigned short temp;
 
    value &= 0x00ff;
    temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0xf0;
@@ -1569,9 +1364,9 @@ SiS_SetSegRegLower(SiS_Private *SiS_Pr, USHORT value)
 }
 
 static void
-SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegRegUpper(struct SiS_Private *SiS_Pr, unsigned short value)
 {
-   USHORT temp;
+   unsigned short temp;
 
    value &= 0x00ff;
    temp = SiS_GetRegByte(SiS_Pr->SiS_P3cb) & 0x0f;
@@ -1583,22 +1378,22 @@ SiS_SetSegRegUpper(SiS_Private *SiS_Pr, USHORT value)
 }
 
 static void
-SiS_SetSegmentReg(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegmentReg(struct SiS_Private *SiS_Pr, unsigned short value)
 {
    SiS_SetSegRegLower(SiS_Pr, value);
    SiS_SetSegRegUpper(SiS_Pr, value);
 }
 
 static void
-SiS_ResetSegmentReg(SiS_Private *SiS_Pr)
+SiS_ResetSegmentReg(struct SiS_Private *SiS_Pr)
 {
    SiS_SetSegmentReg(SiS_Pr, 0);
 }
 
 static void
-SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value)
+SiS_SetSegmentRegOver(struct SiS_Private *SiS_Pr, unsigned short value)
 {
-   USHORT temp = value >> 8;
+   unsigned short temp = value >> 8;
 
    temp &= 0x07;
    temp |= (temp << 4);
@@ -1607,15 +1402,15 @@ SiS_SetSegmentRegOver(SiS_Private *SiS_Pr, USHORT value)
 }
 
 static void
-SiS_ResetSegmentRegOver(SiS_Private *SiS_Pr)
+SiS_ResetSegmentRegOver(struct SiS_Private *SiS_Pr)
 {
    SiS_SetSegmentRegOver(SiS_Pr, 0);
 }
 
 static void
-SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo)
+SiS_ResetSegmentRegisters(struct SiS_Private *SiS_Pr)
 {
-   if((IS_SIS65x) || (HwInfo->jChipType >= SIS_661)) {
+   if((IS_SIS65x) || (SiS_Pr->ChipType >= SIS_661)) {
       SiS_ResetSegmentReg(SiS_Pr);
       SiS_ResetSegmentRegOver(SiS_Pr);
    }
@@ -1625,154 +1420,153 @@ SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo)
 /*             HELPER: GetVBType             */
 /*********************************************/
 
-static void
-SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_GetVBType(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag=0, rev=0, nolcd=0, p4_0f, p4_25, p4_27;
-
-  SiS_Pr->SiS_VBType = 0;
-
-  if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
-     return;
-
-  flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-
-  if(flag > 3) return;
-
-  rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
-
-  if(flag >= 2) {
-     SiS_Pr->SiS_VBType = VB_SIS302B;
-  } else if(flag == 1) {
-     if(rev >= 0xC0) {
-               SiS_Pr->SiS_VBType = VB_SIS301C;
-     } else if(rev >= 0xB0) {
-               SiS_Pr->SiS_VBType = VB_SIS301B;
-       /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
-       nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
-        if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
-     } else {
-        SiS_Pr->SiS_VBType = VB_SIS301;
-     }
-  }
-  if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
-     if(rev >= 0xE0) {
-       flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
-       if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
-       else             SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
-     } else if(rev >= 0xD0) {
-       SiS_Pr->SiS_VBType = VB_SIS301LV;
-     }
-  }
-  if(SiS_Pr->SiS_VBType & (VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
-     p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
-     p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
-     p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
-     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
-     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
-     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
-     if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
-        SiS_Pr->SiS_VBType |= VB_UMC;
-     }
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
-  }
-}
+   unsigned short flag = 0, rev = 0, nolcd = 0;
+   unsigned short p4_0f, p4_25, p4_27;
 
-/*********************************************/
-/*           HELPER: Check RAM size          */
-/*********************************************/
+   SiS_Pr->SiS_VBType = 0;
 
-#ifdef LINUX_KERNEL
-static BOOLEAN
-SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                    USHORT ModeNo, USHORT ModeIdIndex)
-{
-  USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024);
-  USHORT memorysize,modeflag;
-
-  if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     if(ModeNo <= 0x13) {
-        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     } else {
-        modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
-  }
-
-  memorysize = modeflag & MemoryInfoFlag;
-  memorysize >>= MemorySizeShift;              /* Get required memory size */
-  memorysize++;
-
-  if(AdapterMemSize < memorysize) return FALSE;
-  return TRUE;
-}
-#endif
+   if((SiS_Pr->SiS_IF_DEF_LVDS) || (SiS_Pr->SiS_IF_DEF_CONEX))
+      return;
+
+   if(SiS_Pr->ChipType == XGI_20)
+      return;
+
+   flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+
+   if(flag > 3)
+      return;
+
+   rev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+
+   if(flag >= 2) {
+      SiS_Pr->SiS_VBType = VB_SIS302B;
+   } else if(flag == 1) {
+      if(rev >= 0xC0) {
+        SiS_Pr->SiS_VBType = VB_SIS301C;
+      } else if(rev >= 0xB0) {
+        SiS_Pr->SiS_VBType = VB_SIS301B;
+        /* Check if 30xB DH version (no LCD support, use Panel Link instead) */
+        nolcd = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x23);
+        if(!(nolcd & 0x02)) SiS_Pr->SiS_VBType |= VB_NoLCD;
+      } else {
+        SiS_Pr->SiS_VBType = VB_SIS301;
+      }
+   }
+   if(SiS_Pr->SiS_VBType & (VB_SIS301B | VB_SIS301C | VB_SIS302B)) {
+      if(rev >= 0xE0) {
+        flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
+        if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
+        else             SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
+      } else if(rev >= 0xD0) {
+        SiS_Pr->SiS_VBType = VB_SIS301LV;
+      }
+   }
+   if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+      p4_0f = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x0f);
+      p4_25 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x25);
+      p4_27 = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x27);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0x7f);
+      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x25,0x08);
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,0xfd);
+      if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x08) {
+         SiS_Pr->SiS_VBType |= VB_UMC;
+      }
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x27,p4_27);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x25,p4_25);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0f,p4_0f);
+   }
+}
+
+/*********************************************/
+/*           HELPER: Check RAM size          */
+/*********************************************/
+
+#ifdef SIS_LINUX_KERNEL
+static BOOLEAN
+SiS_CheckMemorySize(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex)
+{
+   unsigned short AdapterMemSize = SiS_Pr->VideoMemorySize / (1024*1024);
+   unsigned short modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+   unsigned short memorysize = ((modeflag & MemoryInfoFlag) >> MemorySizeShift) + 1;
+
+   if(!AdapterMemSize) return TRUE;
+
+   if(AdapterMemSize < memorysize) return FALSE;
+   return TRUE;
+}
+#endif
 
 /*********************************************/
 /*           HELPER: Get DRAM type           */
 /*********************************************/
 
 #ifdef SIS315H
-static UCHAR
-SiS_Get310DRAMType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned char
+SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
 {
-   UCHAR data, temp;
+   unsigned char data;
 
    if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
-     data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
+      data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
    } else {
-     if(HwInfo->jChipType >= SIS_340) {
-        /* TODO */
-       data = 0;
-     } if(HwInfo->jChipType >= SIS_661) {
-        data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
-       if(SiS_Pr->SiS_ROMNew) {
-          data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
-       }
-     } else if(IS_SIS550650740) {
-        data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
-     } else {  /* 315, 330 */
-        data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
-        if(HwInfo->jChipType == SIS_330) {
-          if(data > 1) {
-             temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30;
-             switch(temp) {
-             case 0x00: data = 1; break;
-             case 0x10: data = 3; break;
-             case 0x20: data = 3; break;
-             case 0x30: data = 2; break;
-             }
-          } else {
-             data = 0;
-          }
-       }
-     }
+      if(SiS_Pr->ChipType >= XGI_20) {
+         /* Do I need this? SR17 seems to be zero anyway... */
+        data = 0;
+      } else if(SiS_Pr->ChipType >= SIS_340) {
+        /* TODO */
+        data = 0;
+      } if(SiS_Pr->ChipType >= SIS_661) {
+        if(SiS_Pr->SiS_ROMNew) {
+           data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+        } else {
+           data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+        }
+      } else if(IS_SIS550650740) {
+        data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
+      } else { /* 315, 330 */
+        data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x03;
+        if(SiS_Pr->ChipType == SIS_330) {
+           if(data > 1) {
+              switch(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0x30) {
+              case 0x00: data = 1; break;
+              case 0x10: data = 3; break;
+              case 0x20: data = 3; break;
+              case 0x30: data = 2; break;
+              }
+           } else {
+              data = 0;
+           }
+        }
+      }
    }
 
    return data;
 }
 
-static USHORT
-SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+SiS_GetMCLK(struct SiS_Private *SiS_Pr)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index;
-
-  index = SiS_Get310DRAMType(SiS_Pr, HwInfo);
-  if(HwInfo->jChipType >= SIS_661) {
-     if(SiS_Pr->SiS_ROMNew) {
-        return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3))));
-     }
-     return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
-  } else if(index >= 4) {
-     index -= 4;
-     return(SiS_Pr->SiS_MCLKData_1[index].CLOCK);
-  } else {
-     return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
-  }
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short index;
+
+   index = SiS_Get310DRAMType(SiS_Pr);
+   if(SiS_Pr->ChipType >= SIS_661) {
+      if(SiS_Pr->SiS_ROMNew) {
+        return((unsigned short)(SISGETROMW((0x90 + (index * 5) + 3))));
+      }
+      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+   } else if(index >= 4) {
+      return(SiS_Pr->SiS_MCLKData_1[index - 4].CLOCK);
+   } else {
+      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
+   }
 }
 #endif
 
@@ -1780,30 +1574,30 @@ SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*           HELPER: ClearBuffer             */
 /*********************************************/
 
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
 static void
-SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_ClearBuffer(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-  UCHAR SISIOMEMTYPE *VideoMemoryAddress = HwInfo->pjVideoMemoryAddress;
-  ULONG  AdapterMemorySize = HwInfo->ulVideoMemorySize;
-  USHORT SISIOMEMTYPE *pBuffer;
-  int i;
-
-  if(SiS_Pr->SiS_ModeType >= ModeEGA) {
-     if(ModeNo > 0x13) {
-        SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0);
-     } else {
-        pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress;
-        for(i=0; i<0x4000; i++) writew(0x0000, &pBuffer[i]);
-     }
-  } else {
-     if(SiS_Pr->SiS_ModeType < ModeCGA) {
-        pBuffer = (USHORT SISIOMEMTYPE *)VideoMemoryAddress;
-        for(i=0; i<0x4000; i++) writew(0x0720, &pBuffer[i]);
-     } else {
-        SiS_SetMemory(VideoMemoryAddress, 0x8000, 0);
-     }
-  }
+   unsigned char  SISIOMEMTYPE *memaddr = SiS_Pr->VideoMemoryAddress;
+   unsigned int   memsize = SiS_Pr->VideoMemorySize;
+   unsigned short SISIOMEMTYPE *pBuffer;
+   int i;
+
+   if(!memaddr || !memsize) return;
+
+   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
+      if(ModeNo > 0x13) {
+        SiS_SetMemory(memaddr, memsize, 0);
+      } else {
+        pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+        for(i = 0; i < 0x4000; i++) writew(0x0000, &pBuffer[i]);
+      }
+   } else if(SiS_Pr->SiS_ModeType < ModeCGA) {
+      pBuffer = (unsigned short SISIOMEMTYPE *)memaddr;
+      for(i = 0; i < 0x4000; i++) writew(0x0720, &pBuffer[i]);
+   } else {
+      SiS_SetMemory(memaddr, 0x8000, 0);
+   }
 }
 #endif
 
@@ -1812,35 +1606,36 @@ SiS_ClearBuffer(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 /*********************************************/
 
 BOOLEAN
-SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex)
+SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+               unsigned short *ModeIdIndex)
 {
-   UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
+   unsigned char VGAINFO = SiS_Pr->SiS_VGAINFO;
 
-   if(*ModeNo <= 0x13) {
+   if((*ModeNo) <= 0x13) {
 
       if((*ModeNo) <= 0x05) (*ModeNo) |= 0x01;
 
-      for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
-         if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == (*ModeNo)) break;
-         if(SiS_Pr->SiS_SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF)   return FALSE;
+      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+        if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == (*ModeNo)) break;
+        if(SiS_Pr->SiS_SModeIDTable[(*ModeIdIndex)].St_ModeID == 0xFF) return FALSE;
       }
 
-      if(*ModeNo == 0x07) {
-          if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
-          /* else 350 lines */
+      if((*ModeNo) == 0x07) {
+         if(VGAINFO & 0x10) (*ModeIdIndex)++;   /* 400 lines */
+         /* else 350 lines */
       }
-      if(*ModeNo <= 0x03) {
-         if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
-         if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
-         /* else 350 lines  */
+      if((*ModeNo) <= 0x03) {
+        if(!(VGAINFO & 0x80)) (*ModeIdIndex)++;
+        if(VGAINFO & 0x10)    (*ModeIdIndex)++; /* 400 lines  */
+        /* else 350 lines  */
       }
       /* else 200 lines  */
 
    } else {
 
-      for(*ModeIdIndex = 0; ;(*ModeIdIndex)++) {
-         if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == (*ModeNo)) break;
-         if(SiS_Pr->SiS_EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)      return FALSE;
+      for((*ModeIdIndex) = 0; ;(*ModeIdIndex)++) {
+        if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == (*ModeNo)) break;
+        if(SiS_Pr->SiS_EModeIDTable[(*ModeIdIndex)].Ext_ModeID == 0xFF) return FALSE;
       }
 
    }
@@ -1851,10 +1646,10 @@ SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex)
 /*            HELPER: GetModePtr             */
 /*********************************************/
 
-UCHAR
-SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
+unsigned short
+SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-   UCHAR index;
+   unsigned short index;
 
    if(ModeNo <= 0x13) {
       index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
@@ -1865,80 +1660,126 @@ SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
    return index;
 }
 
+/*********************************************/
+/*         HELPERS: Get some indices         */
+/*********************************************/
+
+unsigned short
+SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+      if(UseWide == 1) {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_WIDE;
+      } else {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK_NORM;
+      }
+   } else {
+      return SiS_Pr->SiS_RefIndex[Index].Ext_CRTVCLK;
+   }
+}
+
+unsigned short
+SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide)
+{
+   if(SiS_Pr->SiS_RefIndex[Index].Ext_InfoFlag & HaveWideTiming) {
+      if(UseWide == 1) {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_WIDE;
+      } else {
+         return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC_NORM;
+      }
+   } else {
+      return SiS_Pr->SiS_RefIndex[Index].Ext_CRT1CRTC;
+   }
+}
+
 /*********************************************/
 /*           HELPER: LowModeTests            */
 /*********************************************/
 
 static BOOLEAN
-SiS_DoLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_DoLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-    USHORT temp,temp1,temp2;
-
-    if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-       return(TRUE);
-    temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
-    SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
-    temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
-    SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
-    temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
-    SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
-    SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
-    if((HwInfo->jChipType >= SIS_315H) ||
-       (HwInfo->jChipType == SIS_300)) {
-       if(temp2 == 0x55) return(FALSE);
-       else return(TRUE);
-    } else {
-       if(temp2 != 0x55) return(TRUE);
-       else {
-          SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-          return(FALSE);
-       }
-    }
+   unsigned short temp, temp1, temp2;
+
+   if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
+      return TRUE;
+   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
+   SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
+   temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,0x55);
+   temp2 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,temp1);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
+   if((SiS_Pr->ChipType >= SIS_315H) ||
+      (SiS_Pr->ChipType == SIS_300)) {
+      if(temp2 == 0x55) return FALSE;
+      else return TRUE;
+   } else {
+      if(temp2 != 0x55) return TRUE;
+      else {
+        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
+        return FALSE;
+      }
+   }
 }
 
 static void
-SiS_SetLowModeTest(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_SetLowModeTest(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-    if(SiS_DoLowModeTest(SiS_Pr, ModeNo, HwInfo)) {
-       SiS_Pr->SiS_SetFlag |= LowModeTests;
-    }
+   if(SiS_DoLowModeTest(SiS_Pr, ModeNo)) {
+      SiS_Pr->SiS_SetFlag |= LowModeTests;
+   }
 }
 
 /*********************************************/
-/*            HELPER: ENABLE CRT1            */
+/*        HELPER: OPEN/CLOSE CRT1 CRTC       */
 /*********************************************/
 
 static void
-SiS_SetupCR5x(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_OpenCRTC(struct SiS_Private *SiS_Pr)
+{
+   if(IS_SIS650) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+      if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+   } else if(IS_SIS661741660760) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
+      SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
+      if(!SiS_Pr->SiS_ROMNew) {
+        SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
+      }
+   }
+}
+
+static void
+SiS_CloseCRTC(struct SiS_Private *SiS_Pr)
 {
-    if(IS_SIS650) {
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-         if(IS_SIS651) SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x20);
-         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-       }
-    } else if(IS_SIS661741660760) {
-       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x61,0xf7);
-       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x51,0x1f);
-       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x56,0xe7);
-       if(!SiS_Pr->SiS_ROMNew) {
-         SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x3a,0xef);
-       }
-    }
+#if 0 /* This locks some CRTC registers. We don't want that. */
+   unsigned short temp1 = 0, temp2 = 0;
+
+   if(IS_SIS661741660760) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+         temp1 = 0xa0; temp2 = 0x08;
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x51,0x1f,temp1);
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x56,0xe7,temp2);
+   }
+#endif
 }
 
 static void
-SiS_HandleCRT1(SiS_Private *SiS_Pr)
+SiS_HandleCRT1(struct SiS_Private *SiS_Pr)
 {
-  /* Enable CRT1 gating */
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
+   /* Enable CRT1 gating */
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0xbf);
 #if 0
-  if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
-     if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
-        (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
-        SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
-     }
-  }
+   if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x01)) {
+      if((SiS_GetReg(SiS_Pr->SiS_P3c4,0x15) & 0x0a) ||
+         (SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x01)) {
+         SiS_SetRegOR(SiS_Pr->SiS_P3d4,SiS_Pr->SiS_MyCR63,0x40);
+      }
+   }
 #endif
 }
 
@@ -1946,57 +1787,54 @@ SiS_HandleCRT1(SiS_Private *SiS_Pr)
 /*           HELPER: GetColorDepth           */
 /*********************************************/
 
-USHORT
-SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex)
+unsigned short
+SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex)
 {
-  USHORT ColorDepth[6] = { 1, 2, 4, 4, 6, 8};
-  SHORT  index;
-  USHORT modeflag;
-
-  /* Do NOT check UseCustomMode, will skrew up FIFO */
-  if(ModeNo == 0xfe) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     if(ModeNo <= 0x13)
-       modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     else
-       modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
-
-  index = (modeflag & ModeTypeMask) - ModeEGA;
-  if(index < 0) index = 0;
-  return(ColorDepth[index]);
+   static const unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+   unsigned short modeflag;
+   short index;
+
+   /* Do NOT check UseCustomMode, will skrew up FIFO */
+   if(ModeNo == 0xfe) {
+      modeflag = SiS_Pr->CModeFlag;
+   } else if(ModeNo <= 0x13) {
+      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else {
+      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
+
+   index = (modeflag & ModeTypeMask) - ModeEGA;
+   if(index < 0) index = 0;
+   return ColorDepth[index];
 }
 
 /*********************************************/
 /*             HELPER: GetOffset             */
 /*********************************************/
 
-USHORT
-SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-              USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short RRTI)
 {
-  USHORT xres, temp, colordepth, infoflag;
-
-  if(SiS_Pr->UseCustomMode) {
-     infoflag = SiS_Pr->CInfoFlag;
-     xres = SiS_Pr->CHDisplay;
-  } else {
-     infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-     xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
-  }
-
-  colordepth = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex);
-
-  temp = xres / 16;
-  if(infoflag & InterlaceMode) temp <<= 1;
-  temp *= colordepth;
-  if(xres % 16) {
-     colordepth >>= 1;
-     temp += colordepth;
-  }
-
-  return(temp);
+   unsigned short xres, temp, colordepth, infoflag;
+
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+      xres = SiS_Pr->CHDisplay;
+   } else {
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+      xres = SiS_Pr->SiS_RefIndex[RRTI].XRes;
+   }
+
+   colordepth = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex);
+
+   temp = xres / 16;
+   if(infoflag & InterlaceMode) temp <<= 1;
+   temp *= colordepth;
+   if(xres % 16) temp += (colordepth >> 1);
+
+   return temp;
 }
 
 /*********************************************/
@@ -2004,55 +1842,29 @@ SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetSeqRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
 {
-   UCHAR SRdata;
-   USHORT i;
+   unsigned char SRdata;
+   int i;
 
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);             /* Set SR0  */
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x00,0x03);
 
-   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0];
+   /* or "display off"  */
+   SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[0] | 0x20;
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-         SRdata |= 0x01;
-      }
-      if(HwInfo->jChipType >= SIS_661) {
-         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-               SRdata |= 0x01;                         /* 8 dot clock  */
-            }
-        }
-      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-         if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-               SRdata |= 0x01;                         /* 8 dot clock  */
-            }
-        }
-      }
-   }
+   /* determine whether to force x8 dotclock */
+   if((SiS_Pr->SiS_VBType & VB_SISVB) || (SiS_Pr->SiS_IF_DEF_LVDS)) {
 
-   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-            if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-               SRdata |= 0x01;                         /* 8 dot clock  */
-            }
-         }
-      }
-      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-            SRdata |= 0x01;                            /* 8 dot clock  */
-         }
-      }
-   }
+      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+         if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)    SRdata |= 0x01;
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) SRdata |= 0x01;
 
-   SRdata |= 0x20;                                     /* screen off  */
+   }
 
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x01,SRdata);
 
    for(i = 2; i <= 4; i++) {
-      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i-1];
+      SRdata = SiS_Pr->SiS_StandTable[StandTableIndex].SR[i - 1];
       SiS_SetReg(SiS_Pr->SiS_P3c4,i,SRdata);
    }
 }
@@ -2062,17 +1874,17 @@ SiS_SetSeqRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static void
-SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetMiscRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
 {
-   UCHAR Miscdata;
+   unsigned char Miscdata;
 
    Miscdata = SiS_Pr->SiS_StandTable[StandTableIndex].MISC;
 
-   if(HwInfo->jChipType < SIS_661) {
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-            Miscdata |= 0x0C;
-         }
+   if(SiS_Pr->ChipType < SIS_661) {
+      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+          Miscdata |= 0x0C;
+        }
       }
    }
 
@@ -2084,33 +1896,34 @@ SiS_SetMiscRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex, PSIS_HW_INFO HwInfo
 /*********************************************/
 
 static void
-SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                USHORT StandTableIndex)
+SiS_SetCRTCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
 {
-  UCHAR CRTCdata;
-  USHORT i;
-
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);                       /* Unlock CRTC */
-
-  for(i = 0; i <= 0x18; i++) {
-     CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
-     SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);                     /* Set CRTC(3d4) */
-  }
-  if(HwInfo->jChipType >= SIS_661) {
-     SiS_SetupCR5x(SiS_Pr, HwInfo);
-     for(i = 0x13; i <= 0x14; i++) {
-        CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
-        SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
-     }
-  } else if( ( (HwInfo->jChipType == SIS_630) ||
-               (HwInfo->jChipType == SIS_730) )  &&
-             (HwInfo->jChipRevision >= 0x30) ) {                  /* for 630S0 */
-     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-           SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
-        }
-     }
-  }
+   unsigned char  CRTCdata;
+   unsigned short i;
+
+   /* Unlock CRTC */
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i = 0; i <= 0x18; i++) {
+      CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+      SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+   }
+
+   if(SiS_Pr->ChipType >= SIS_661) {
+      SiS_OpenCRTC(SiS_Pr);
+      for(i = 0x13; i <= 0x14; i++) {
+        CRTCdata = SiS_Pr->SiS_StandTable[StandTableIndex].CRTC[i];
+        SiS_SetReg(SiS_Pr->SiS_P3d4,i,CRTCdata);
+      }
+   } else if( ( (SiS_Pr->ChipType == SIS_630) ||
+               (SiS_Pr->ChipType == SIS_730) )  &&
+             (SiS_Pr->ChipRevision >= 0x30) ) {
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+           SiS_SetReg(SiS_Pr->SiS_P3d4,0x18,0xFE);
+        }
+      }
+   }
 }
 
 /*********************************************/
@@ -2118,64 +1931,58 @@ SiS_SetCRTCRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 /*********************************************/
 
 static void
-SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex,
-               PSIS_HW_INFO HwInfo)
+SiS_SetATTRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
 {
-   UCHAR ARdata;
-   USHORT i;
+   unsigned char  ARdata;
+   unsigned short i;
 
    for(i = 0; i <= 0x13; i++) {
       ARdata = SiS_Pr->SiS_StandTable[StandTableIndex].ATTR[i];
-#if 0
-      if((i <= 0x0f) || (i == 0x11)) {
-         if(ds:489 & 0x08) {
-           continue;
-         }
-      }
-#endif
+
       if(i == 0x13) {
-         /* Pixel shift. If screen on LCD or TV is shifted left or right,
-          * this might be the cause.
-          */
-         if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-            if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  ARdata=0;
-         }
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-               if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-                  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
-               }
-            }
-         }
-        if(HwInfo->jChipType >= SIS_661) {
+        /* Pixel shift. If screen on LCD or TV is shifted left or right,
+         * this might be the cause.
+         */
+        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) ARdata = 0;
+        }
+        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+           if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+              if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+                 if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+              }
+           }
+        }
+        if(SiS_Pr->ChipType >= SIS_661) {
            if(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
-              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
+              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
            }
         } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-            if(HwInfo->jChipType >= SIS_315H) {
+           if(SiS_Pr->ChipType >= SIS_315H) {
               if(IS_SIS550650740660) {
-                 /* 315, 330 don't do this */
-                 if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
-                    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata=0;
-                 } else {
-                    ARdata = 0;
-                 }
+                 /* 315, 330 don't do this */
+                 if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
+                    if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
+                 } else {
+                    ARdata = 0;
+                 }
               }
            } else {
-               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  ARdata=0;
+              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) ARdata = 0;
            }
-         }
+        }
       }
-      SiS_GetRegByte(SiS_Pr->SiS_P3da);                         /* reset 3da  */
-      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);                       /* set index  */
-      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata);                  /* set data   */
+      SiS_GetRegByte(SiS_Pr->SiS_P3da);                /* reset 3da  */
+      SiS_SetRegByte(SiS_Pr->SiS_P3c0,i);      /* set index  */
+      SiS_SetRegByte(SiS_Pr->SiS_P3c0,ARdata); /* set data   */
    }
-   SiS_GetRegByte(SiS_Pr->SiS_P3da);                            /* reset 3da  */
-   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);                       /* set index  */
-   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);                       /* set data   */
+
+   SiS_GetRegByte(SiS_Pr->SiS_P3da);           /* reset 3da  */
+   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x14);      /* set index  */
+   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x00);      /* set data   */
 
    SiS_GetRegByte(SiS_Pr->SiS_P3da);
-   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);                      /* Enable Attribute  */
+   SiS_SetRegByte(SiS_Pr->SiS_P3c0,0x20);      /* Enable Attribute  */
    SiS_GetRegByte(SiS_Pr->SiS_P3da);
 }
 
@@ -2184,10 +1991,10 @@ SiS_SetATTRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex,
 /*********************************************/
 
 static void
-SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex)
+SiS_SetGRCRegs(struct SiS_Private *SiS_Pr, unsigned short StandTableIndex)
 {
-   UCHAR GRdata;
-   USHORT i;
+   unsigned char  GRdata;
+   unsigned short i;
 
    for(i = 0; i <= 0x08; i++) {
       GRdata = SiS_Pr->SiS_StandTable[StandTableIndex].GRC[i];
@@ -2205,22 +2012,22 @@ SiS_SetGRCRegs(SiS_Private *SiS_Pr, USHORT StandTableIndex)
 /*********************************************/
 
 static void
-SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_ClearExt1Regs(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-  USHORT i;
+   unsigned short i;
 
-  for(i = 0x0A; i <= 0x0E; i++) {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
-  }
+   for(i = 0x0A; i <= 0x0E; i++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,i,0x00);
+   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
-     if(ModeNo <= 0x13) {
-        if(ModeNo == 0x06 || ModeNo >= 0x0e) {
-          SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
-       }
-     }
-  }
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x37,0xFE);
+      if(ModeNo <= 0x13) {
+        if(ModeNo == 0x06 || ModeNo >= 0x0e) {
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x0e,0x20);
+        }
+      }
+   }
 }
 
 /*********************************************/
@@ -2228,32 +2035,24 @@ SiS_ClearExt1Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 /*********************************************/
 
 static void
-SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ResetCRT1VCLK(struct SiS_Private *SiS_Pr)
 {
-   if(HwInfo->jChipType >= SIS_315H) {
-      if(HwInfo->jChipType < SIS_661) {
-         if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(SiS_Pr->ChipType < SIS_661) {
+        if(SiS_Pr->SiS_IF_DEF_LVDS == 0) return;
       }
    } else {
       if((SiS_Pr->SiS_IF_DEF_LVDS == 0) &&
-         (!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
+        (!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
         return;
       }
    }
 
-   if(HwInfo->jChipType >= SIS_315H) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xCF,0x20);
-   } else {
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x20);
-   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x20);
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[1].SR2B);
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[1].SR2C);
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
-   if(HwInfo->jChipType >= SIS_315H) {
-      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
-   } else {
-      SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x10);
-   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x31,0xcf,0x10);
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,SiS_Pr->SiS_VCLKData[0].SR2B);
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,SiS_Pr->SiS_VCLKData[0].SR2C);
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
@@ -2264,19 +2063,19 @@ SiS_ResetCRT1VCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static void
-SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex)
+SiS_SetCRT1Sync(struct SiS_Private *SiS_Pr, unsigned short RRTI)
 {
-  USHORT sync;
+   unsigned short sync;
 
-  if(SiS_Pr->UseCustomMode) {
-     sync = SiS_Pr->CInfoFlag >> 8;
-  } else {
-     sync = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8;
-  }
+   if(SiS_Pr->UseCustomMode) {
+      sync = SiS_Pr->CInfoFlag >> 8;
+   } else {
+      sync = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag >> 8;
+   }
 
-  sync &= 0xC0;
-  sync |= 0x2f;
-  SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
+   sync &= 0xC0;
+   sync |= 0x2f;
+   SiS_SetRegByte(SiS_Pr->SiS_P3c2,sync);
 }
 
 /*********************************************/
@@ -2284,72 +2083,67 @@ SiS_SetCRT1Sync(SiS_Private *SiS_Pr, USHORT RefreshRateTableIndex)
 /*********************************************/
 
 static void
-SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                USHORT RefreshRateTableIndex,
-               PSIS_HW_INFO HwInfo)
+SiS_SetCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short RRTI)
 {
-  UCHAR  index;
-  USHORT temp,i,j,modeflag;
-
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);           /* unlock cr0-7 */
-
-  if(SiS_Pr->UseCustomMode) {
-
-     modeflag = SiS_Pr->CModeFlag;
-
-     for(i=0,j=0;i<=7;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
-     }
-     for(j=0x10;i<=10;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
-     }
-     for(j=0x15;i<=12;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
-     }
-     for(j=0x0A;i<=15;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
-     }
-
-     temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
-     temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
-     if(modeflag & DoubleScanMode) temp |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
-  } else {
-
-     if(ModeNo <= 0x13) {
-        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     } else {
-        modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     }
-
-     index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
-     for(i=0,j=0;i<=7;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-     }
-     for(j=0x10;i<=10;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-     }
-     for(j=0x15;i<=12;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-     }
-     for(j=0x0A;i<=15;i++,j++) {
-        SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->SiS_CRT1Table[index].CR[i]);
-     }
-
-     temp = SiS_Pr->SiS_CRT1Table[index].CR[16] & 0xE0;
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,temp);
-
-     temp = ((SiS_Pr->SiS_CRT1Table[index].CR[16]) & 0x01) << 5;
-     if(modeflag & DoubleScanMode)  temp |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
-
-  }
-
-  if(SiS_Pr->SiS_ModeType > ModeVGA) SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+   unsigned short temp, i, j, modeflag;
+   unsigned char  *crt1data = NULL;
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->UseCustomMode) {
+
+      crt1data = &SiS_Pr->CCRT1CRTC[0];
+
+   } else {
+
+      temp = SiS_GetRefCRT1CRTC(SiS_Pr, RRTI, SiS_Pr->SiS_UseWide);
+
+      /* Alternate for 1600x1200 LCDA */
+      if((temp == 0x20) && (SiS_Pr->Alternate1600x1200)) temp = 0x57;
+
+      crt1data = (unsigned char *)&SiS_Pr->SiS_CRT1Table[temp].CR[0];
+
+   }
+
+   /* unlock cr0-7 */
+   SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+   for(i = 0, j = 0; i <= 7; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+   }
+   for(j = 0x10; i <= 10; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+   }
+   for(j = 0x15; i <= 12; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,j,crt1data[i]);
+   }
+   for(j = 0x0A; i <= 15; i++, j++) {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,j,crt1data[i]);
+   }
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x0E,crt1data[16] & 0xE0);
+
+   temp = (crt1data[16] & 0x01) << 5;
+   if(modeflag & DoubleScanMode) temp |= 0x80;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,temp);
+
+   if(SiS_Pr->SiS_ModeType > ModeVGA) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x14,0x4F);
+   }
+
+#ifdef SIS315H
+   if(SiS_Pr->ChipType == XGI_20) {
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x04,crt1data[4] - 1);
+      if(!(temp = crt1data[5] & 0x1f)) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x0c,0xfb);
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x05,0xe0,((temp - 1) & 0x1f));
+      temp = (crt1data[16] >> 5) + 3;
+      if(temp > 7) temp -= 7;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0e,0x1f,(temp << 5));
+   }
+#endif
 }
 
 /*********************************************/
@@ -2359,33 +2153,32 @@ SiS_SetCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                  USHORT RefreshRateTableIndex,
-                 PSIS_HW_INFO HwInfo)
+SiS_SetCRT1Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short RRTI)
 {
-   USHORT temp, DisplayUnit, infoflag;
+   unsigned short temp, DisplayUnit, infoflag;
 
    if(SiS_Pr->UseCustomMode) {
       infoflag = SiS_Pr->CInfoFlag;
    } else {
-      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
    }
 
-   DisplayUnit = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,
-                              RefreshRateTableIndex,HwInfo);
+   DisplayUnit = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
 
    temp = (DisplayUnit >> 8) & 0x0f;
    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,temp);
 
-   temp = DisplayUnit & 0xFF;
-   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,temp);
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,DisplayUnit & 0xFF);
 
    if(infoflag & InterlaceMode) DisplayUnit >>= 1;
 
    DisplayUnit <<= 5;
-   temp = (DisplayUnit & 0xff00) >> 8;
+   temp = (DisplayUnit >> 8) + 1;
    if(DisplayUnit & 0xff) temp++;
-   temp++;
+   if(SiS_Pr->ChipType == XGI_20) {
+      if(ModeNo == 0x4a || ModeNo == 0x49) temp--;
+   }
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x10,temp);
 }
 
@@ -2394,39 +2187,49 @@ SiS_SetCRT1Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetCRT1VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short RRTI)
 {
-  USHORT  index=0, clka, clkb;
-
-  if(SiS_Pr->UseCustomMode) {
-     clka = SiS_Pr->CSR2B;
-     clkb = SiS_Pr->CSR2C;
-  } else {
-     index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-     if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-        clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
-       clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
-     } else {
-        clka = SiS_Pr->SiS_VCLKData[index].SR2B;
-       clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
-     }
-  }
-
-  if(HwInfo->jChipType >= SIS_315H) {
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
-  } else {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x31,0x00);
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2B,clka);
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x2C,clkb);
-
-  if(HwInfo->jChipType >= SIS_315H) {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
-  } else {
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
-  }
+   unsigned short index = 0, clka, clkb;
+
+   if(SiS_Pr->UseCustomMode) {
+      clka = SiS_Pr->CSR2B;
+      clkb = SiS_Pr->CSR2C;
+   } else {
+      index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+      if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+        (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+        /* Alternate for 1600x1200 LCDA */
+        if((index == 0x21) && (SiS_Pr->Alternate1600x1200)) index = 0x72;
+        clka = SiS_Pr->SiS_VBVCLKData[index].Part4_A;
+        clkb = SiS_Pr->SiS_VBVCLKData[index].Part4_B;
+      } else {
+        clka = SiS_Pr->SiS_VCLKData[index].SR2B;
+        clkb = SiS_Pr->SiS_VCLKData[index].SR2C;
+      }
+   }
+
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xCF);
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,clka);
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+
+   if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef SIS315H
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x01);
+      if(SiS_Pr->ChipType == XGI_20) {
+         unsigned short mf = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+        if(mf & HalfDCLK) {
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,SiS_GetReg(SiS_Pr->SiS_P3c4,0x2b));
+           clkb = SiS_GetReg(SiS_Pr->SiS_P3c4,0x2c);
+           clkb = (((clkb & 0x1f) << 1) + 1) | (clkb & 0xe0);
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,clkb);
+        }
+      }
+#endif
+   } else {
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x2D,0x80);
+   }
 }
 
 /*********************************************/
@@ -2434,802 +2237,730 @@ SiS_SetCRT1VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 #ifdef SIS300
-static USHORT
-SiS_DoCalcDelay(SiS_Private *SiS_Pr, USHORT MCLK, USHORT VCLK, USHORT colordepth, USHORT key)
+void
+SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+               unsigned short *idx2)
 {
-  const UCHAR ThLowA[]   = { 61, 3,52, 5,68, 7,100,11,
-                             43, 3,42, 5,54, 7, 78,11,
-                             34, 3,37, 5,47, 7, 67,11 };
-
-  const UCHAR ThLowB[]   = { 81, 4,72, 6,88, 8,120,12,
-                             55, 4,54, 6,66, 8, 90,12,
-                             42, 4,45, 6,55, 8, 75,12 };
-
-  const UCHAR ThTiming[] = {  1, 2, 2, 3, 0, 1,  1, 2 };
-
-  USHORT tempah, tempal, tempcl, tempbx, temp;
-  ULONG  longtemp;
-
-  tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
-  tempah &= 0x62;
-  tempah >>= 1;
-  tempal = tempah;
-  tempah >>= 3;
-  tempal |= tempah;
-  tempal &= 0x07;
-  tempcl = ThTiming[tempal];
-  tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
-  tempbx >>= 6;
-  tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-  tempah >>= 4;
-  tempah &= 0x0c;
-  tempbx |= tempah;
-  tempbx <<= 1;
-  if(key == 0) {
-     tempal = ThLowA[tempbx + 1];
-     tempal *= tempcl;
-     tempal += ThLowA[tempbx];
-  } else {
-     tempal = ThLowB[tempbx + 1];
-     tempal *= tempcl;
-     tempal += ThLowB[tempbx];
-  }
-  longtemp = tempal * VCLK * colordepth;
-  temp = longtemp % (MCLK * 16);
-  longtemp /= (MCLK * 16);
-  if(temp) longtemp++;
-  return((USHORT)longtemp);
+   unsigned short temp1, temp2;
+   static const unsigned char ThTiming[8] = {
+               1, 2, 2, 3, 0, 1, 1, 2
+   };
+
+   temp1 = temp2 = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x62) >> 1;
+   (*idx2) = (unsigned short)(ThTiming[((temp2 >> 3) | temp1) & 0x07]);
+   (*idx1) = (unsigned short)(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6) & 0x03;
+   (*idx1) |= (unsigned short)(((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 4) & 0x0c));
+   (*idx1) <<= 1;
 }
 
-static USHORT
-SiS_CalcDelay(SiS_Private *SiS_Pr, USHORT VCLK, USHORT colordepth, USHORT MCLK)
+static unsigned short
+SiS_GetFIFOThresholdA300(unsigned short idx1, unsigned short idx2)
 {
-  USHORT tempax, tempbx;
-
-  tempbx = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
-  tempax = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
-  if(tempax < 4) tempax = 4;
-  tempax -= 4;
-  if(tempbx < tempax) tempbx = tempax;
-  return(tempbx);
-}
+   static const unsigned char ThLowA[8 * 3] = {
+               61, 3,52, 5,68, 7,100,11,
+               43, 3,42, 5,54, 7, 78,11,
+               34, 3,37, 5,47, 7, 67,11
+   };
 
-static void
-SiS_SetCRT1FIFO_300(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo,
-                    USHORT RefreshRateTableIndex)
-{
-  USHORT  ThresholdLow = 0;
-  USHORT  index, VCLK, MCLK, colorth=0;
-  USHORT  tempah, temp;
-
-  if(ModeNo > 0x13) {
-
-     if(SiS_Pr->UseCustomMode) {
-        VCLK = SiS_Pr->CSRClock;
-     } else {
-        index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-        index &= 0x3F;
-        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;             /* Get VCLK  */
-     }
-
-     switch (SiS_Pr->SiS_ModeType - ModeEGA) {     /* Get half colordepth */
-        case 0 : colorth = 1; break;
-        case 1 : colorth = 1; break;
-        case 2 : colorth = 2; break;
-        case 3 : colorth = 2; break;
-        case 4 : colorth = 3; break;
-        case 5 : colorth = 4; break;
-     }
-
-     index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
-     index &= 0x07;
-     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;           /* Get MCLK  */
-
-     tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-     tempah &= 0xc3;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,tempah);
-
-     do {
-        ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK);
-        ThresholdLow++;
-        if(ThresholdLow < 0x13) break;
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
-        ThresholdLow = 0x13;
-        tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
-        tempah >>= 6;
-        if(!(tempah)) break;
-        tempah--;
-        tempah <<= 6;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,tempah);
-     } while(0);
-
-  } else ThresholdLow = 2;
-
-  /* Write CRT/CPU threshold low, CRT/Engine threshold high */
-  temp = (ThresholdLow << 4) | 0x0f;
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
-
-  temp = (ThresholdLow & 0x10) << 1;
-  if(ModeNo > 0x13) temp |= 0x40;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
-
-  /* What is this? */
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
-
-  /* Write CRT/CPU threshold high */
-  temp = ThresholdLow + 3;
-  if(temp > 0x0f) temp = 0x0f;
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
+   return (unsigned short)((ThLowA[idx1 + 1] * idx2) + ThLowA[idx1]);
 }
 
-static USHORT
-SiS_CalcDelay2(SiS_Private *SiS_Pr, UCHAR key, PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2)
 {
-  USHORT data,index;
-  const UCHAR  LatencyFactor[] = {
-       97, 88, 86, 79, 77, 00,       /*; 64  bit    BQ=2   */
-        00, 87, 85, 78, 76, 54,       /*; 64  bit    BQ=1   */
-        97, 88, 86, 79, 77, 00,       /*; 128 bit    BQ=2   */
-        00, 79, 77, 70, 68, 48,       /*; 128 bit    BQ=1   */
-        80, 72, 69, 63, 61, 00,       /*; 64  bit    BQ=2   */
-        00, 70, 68, 61, 59, 37,       /*; 64  bit    BQ=1   */
-        86, 77, 75, 68, 66, 00,       /*; 128 bit    BQ=2   */
-        00, 68, 66, 59, 57, 37        /*; 128 bit    BQ=1   */
-  };
-  const UCHAR  LatencyFactor730[] = {
-         69, 63, 61,
-        86, 79, 77,
-       103, 96, 94,
-       120,113,111,
-       137,130,128,    /* --- Table ends with this entry, data below */
-       137,130,128,    /* to avoid using illegal values              */
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-  };
-
-  if(HwInfo->jChipType == SIS_730) {
-     index = ((key & 0x0f) * 3) + ((key & 0xC0) >> 6);
-     data = LatencyFactor730[index];
-  } else {
-     index = (key & 0xE0) >> 5;
-     if(key & 0x10) index +=6;
-     if(!(key & 0x01)) index += 24;
-     data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-     if(data & 0x0080) index += 12;
-     data = LatencyFactor[index];
-  }
-  return(data);
+   static const unsigned char ThLowB[8 * 3] = {
+               81, 4,72, 6,88, 8,120,12,
+               55, 4,54, 6,66, 8, 90,12,
+               42, 4,45, 6,55, 8, 75,12
+   };
+
+   return (unsigned short)((ThLowB[idx1 + 1] * idx2) + ThLowB[idx1]);
 }
 
-static void
-SiS_SetCRT1FIFO_630(SiS_Private *SiS_Pr, USHORT ModeNo,
-                   PSIS_HW_INFO HwInfo,
-                    USHORT RefreshRateTableIndex)
+static unsigned short
+SiS_DoCalcDelay(struct SiS_Private *SiS_Pr, unsigned short MCLK, unsigned short VCLK,
+               unsigned short colordepth, unsigned short key)
 {
-  USHORT  i,index,data,VCLK,MCLK,colorth=0;
-  ULONG   B,eax,bl,data2;
-  USHORT  ThresholdLow=0;
-  UCHAR   FQBQData[]= {
-       0x01,0x21,0x41,0x61,0x81,
-        0x31,0x51,0x71,0x91,0xb1,
-        0x00,0x20,0x40,0x60,0x80,
-        0x30,0x50,0x70,0x90,0xb0,
-       0xFF
-  };
-  UCHAR   FQBQData730[]= {
-        0x34,0x74,0xb4,
-       0x23,0x63,0xa3,
-       0x12,0x52,0x92,
-       0x01,0x41,0x81,
-       0x00,0x40,0x80,
-       0xff
-  };
-
-  i=0;
-  if(ModeNo > 0x13) {
-    if(SiS_Pr->UseCustomMode) {
-       VCLK = SiS_Pr->CSRClock;
-    } else {
-       index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-       index &= 0x3F;
-       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;          /* Get VCLK  */
-    }
-
-    index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
-    index &= 0x07;
-    MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;           /* Get MCLK  */
-
-    data2 = SiS_Pr->SiS_ModeType - ModeEGA;      /* Get half colordepth */
-    switch (data2) {
-        case 0 : colorth = 1; break;
-        case 1 : colorth = 1; break;
-        case 2 : colorth = 2; break;
-        case 3 : colorth = 2; break;
-        case 4 : colorth = 3; break;
-        case 5 : colorth = 4; break;
-    }
-
-    if(HwInfo->jChipType == SIS_730) {
-
-       do {
-          B = SiS_CalcDelay2(SiS_Pr, FQBQData730[i], HwInfo) * VCLK * colorth;
-         bl = B / (MCLK * 16);
-
-          if(B == bl * 16 * MCLK) {
-             bl = bl + 1;
-          } else {
-             bl = bl + 2;
-          }
-
-          if(bl > 0x13) {
-             if(FQBQData730[i+1] == 0xFF) {
-                ThresholdLow = 0x13;
-                break;
-             }
-             i++;
-          } else {
-             ThresholdLow = bl;
-             break;
-          }
-       } while(FQBQData730[i] != 0xFF);
+   unsigned short idx1, idx2;
+   unsigned int   longtemp = VCLK * colordepth;
 
-    } else {
+   SiS_GetFIFOThresholdIndex300(SiS_Pr, &idx1, &idx2);
 
-       do {
-          B = SiS_CalcDelay2(SiS_Pr, FQBQData[i], HwInfo) * VCLK * colorth;
-          bl = B / (MCLK * 16);
+   if(key == 0) {
+      longtemp *= SiS_GetFIFOThresholdA300(idx1, idx2);
+   } else {
+      longtemp *= SiS_GetFIFOThresholdB300(idx1, idx2);
+   }
+   idx1 = longtemp % (MCLK * 16);
+   longtemp /= (MCLK * 16);
+   if(idx1) longtemp++;
+   return (unsigned short)longtemp;
+}
 
-          if(B == bl * 16 * MCLK) {
-             bl = bl + 1;
-          } else {
-             bl = bl + 2;
-          }
+static unsigned short
+SiS_CalcDelay(struct SiS_Private *SiS_Pr, unsigned short VCLK,
+               unsigned short colordepth, unsigned short MCLK)
+{
+   unsigned short temp1, temp2;
+
+   temp2 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 0);
+   temp1 = SiS_DoCalcDelay(SiS_Pr, MCLK, VCLK, colordepth, 1);
+   if(temp1 < 4) temp1 = 4;
+   temp1 -= 4;
+   if(temp2 < temp1) temp2 = temp1;
+   return temp2;
+}
 
-          if(bl > 0x13) {
-             if(FQBQData[i+1] == 0xFF) {
-                ThresholdLow = 0x13;
-                break;
-             }
-             i++;
-          } else {
-             ThresholdLow = bl;
-             break;
-          }
-       } while(FQBQData[i] != 0xFF);
-    }
-  }
-  else {
-    if(HwInfo->jChipType == SIS_730) {
-    } else {
-      i = 9;
-    }
-    ThresholdLow = 0x02;
-  }
+static void
+SiS_SetCRT1FIFO_300(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short RefreshRateTableIndex)
+{
+   unsigned short ThresholdLow = 0;
+   unsigned short temp, index, VCLK, MCLK, colorth;
+   static const unsigned short colortharray[6] = { 1, 1, 2, 2, 3, 4 };
 
-  /* Write foreground and background queue */
-  if(HwInfo->jChipType == SIS_730) {
-
-     data2 = FQBQData730[i];
-     data2 = (data2 & 0xC0) >> 5;
-     data2 <<= 8;
-
-#ifdef LINUX_KERNEL
-     SiS_SetRegLong(0xcf8,0x80000050);
-     eax = SiS_GetRegLong(0xcfc);
-     eax &= 0xfffff9ff;
-     eax |= data2;
-     SiS_SetRegLong(0xcfc,eax);
-#else
-     /* We use pci functions X offers. We use pcitag 0, because
-      * we want to read/write to the host bridge (which is always
-      * 00:00.0 on 630, 730 and 540), not the VGA device.
-      */
-     eax = pciReadLong(0x00000000, 0x50);
-     eax &= 0xfffff9ff;
-     eax |= data2;
-     pciWriteLong(0x00000000, 0x50, eax);
-#endif
+   if(ModeNo > 0x13) {
 
-     /* Write GUI grant timer (PCI config 0xA3) */
-     data2 = FQBQData730[i] << 8;
-     data2 = (data2 & 0x0f00) | ((data2 & 0x3000) >> 8);
-     data2 <<= 20;
-
-#ifdef LINUX_KERNEL
-     SiS_SetRegLong(0xcf8,0x800000A0);
-     eax = SiS_GetRegLong(0xcfc);
-     eax &= 0x00ffffff;
-     eax |= data2;
-     SiS_SetRegLong(0xcfc,eax);
-#else
-     eax = pciReadLong(0x00000000, 0xA0);
-     eax &= 0x00ffffff;
-     eax |= data2;
-     pciWriteLong(0x00000000, 0xA0, eax);
-#endif
+      /* Get VCLK  */
+      if(SiS_Pr->UseCustomMode) {
+        VCLK = SiS_Pr->CSRClock;
+      } else {
+        index = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+      }
 
-  } else {
+      /* Get half colordepth */
+      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
 
-     data2 = FQBQData[i];
-     data2 = (data2 & 0xf0) >> 4;
-     data2 <<= 24;
+      /* Get MCLK  */
+      index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A) & 0x07;
+      MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
 
-#ifdef LINUX_KERNEL
-     SiS_SetRegLong(0xcf8,0x80000050);
-     eax = SiS_GetRegLong(0xcfc);
-     eax &= 0xf0ffffff;
-     eax |= data2;
-     SiS_SetRegLong(0xcfc,eax);
-#else
-     eax = pciReadLong(0x00000000, 0x50);
-     eax &= 0xf0ffffff;
-     eax |= data2;
-     pciWriteLong(0x00000000, 0x50, eax);
-#endif
+      temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xc3;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3c,temp);
 
-     /* Write GUI grant timer (PCI config 0xA3) */
-     data2 = FQBQData[i];
-     data2 &= 0x0f;
-     data2 <<= 24;
-
-#ifdef LINUX_KERNEL
-     SiS_SetRegLong(0xcf8,0x800000A0);
-     eax = SiS_GetRegLong(0xcfc);
-     eax &= 0xf0ffffff;
-     eax |= data2;
-     SiS_SetRegLong(0xcfc,eax);
-#else
-     eax = pciReadLong(0x00000000, 0xA0);
-     eax &= 0xf0ffffff;
-     eax |= data2;
-     pciWriteLong(0x00000000, 0xA0, eax);
-#endif
+      do {
+        ThresholdLow = SiS_CalcDelay(SiS_Pr, VCLK, colorth, MCLK) + 1;
+        if(ThresholdLow < 0x13) break;
+        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x16,0xfc);
+        ThresholdLow = 0x13;
+        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) >> 6;
+        if(!temp) break;
+        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x16,0x3f,((temp - 1) << 6));
+      } while(0);
 
-  }
+   } else ThresholdLow = 2;
 
-  /* Write CRT/CPU threshold low, CRT/Engine threshold high */
-  data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
+   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+   temp = (ThresholdLow << 4) | 0x0f;
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,temp);
 
-  data = (ThresholdLow & 0x10) << 1;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
+   temp = (ThresholdLow & 0x10) << 1;
+   if(ModeNo > 0x13) temp |= 0x40;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0f,0x9f,temp);
 
-  /* What is this? */
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
+   /* What is this? */
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
 
-  /* Write CRT/CPU threshold high (gap = 3) */
-  data = ThresholdLow + 3;
-  if(data > 0x0f) data = 0x0f;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
+   /* Write CRT/CPU threshold high */
+   temp = ThresholdLow + 3;
+   if(temp > 0x0f) temp = 0x0f;
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x09,temp);
 }
-#endif
 
-#ifdef SIS315H
-static void
-SiS_SetCRT1FIFO_310(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                    PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index)
 {
-  USHORT modeflag;
-
-  /* disable auto-threshold */
-  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
-
-  if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
-
-  SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
-  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
-  if(ModeNo > 0x13) {
-     if(HwInfo->jChipType >= SIS_661) {
-        if(!(modeflag & HalfDCLK)) {
-          SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-          SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-       }
-     } else {
-        if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
-           SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
-           SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
-       }
-     }
-  }
+   static const unsigned char LatencyFactor[] = {
+               97, 88, 86, 79, 77,  0,       /* 64  bit    BQ=2   */
+                0, 87, 85, 78, 76, 54,       /* 64  bit    BQ=1   */
+               97, 88, 86, 79, 77,  0,       /* 128 bit    BQ=2   */
+                0, 79, 77, 70, 68, 48,       /* 128 bit    BQ=1   */
+               80, 72, 69, 63, 61,  0,       /* 64  bit    BQ=2   */
+                0, 70, 68, 61, 59, 37,       /* 64  bit    BQ=1   */
+               86, 77, 75, 68, 66,  0,       /* 128 bit    BQ=2   */
+                0, 68, 66, 59, 57, 37        /* 128 bit    BQ=1   */
+   };
+   static const unsigned char LatencyFactor730[] = {
+                69, 63, 61,
+                86, 79, 77,
+               103, 96, 94,
+               120,113,111,
+               137,130,128
+   };
+
+   if(SiS_Pr->ChipType == SIS_730) {
+      return (unsigned short)LatencyFactor730[index];
+   } else {
+      return (unsigned short)LatencyFactor[index];
+   }
 }
-#endif
 
-/*********************************************/
-/*              MODE REGISTERS               */
-/*********************************************/
+static unsigned short
+SiS_CalcDelay2(struct SiS_Private *SiS_Pr, unsigned char key)
+{
+   unsigned short index;
+
+   if(SiS_Pr->ChipType == SIS_730) {
+      index = ((key & 0x0f) * 3) + ((key & 0xc0) >> 6);
+   } else {
+      index = (key & 0xe0) >> 5;
+      if(key & 0x10)    index +=  6;
+      if(!(key & 0x01)) index += 24;
+      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
+   }
+   return SiS_GetLatencyFactor630(SiS_Pr, index);
+}
 
 static void
-SiS_SetVCLKState(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                 USHORT ModeNo, USHORT RefreshRateTableIndex,
-                 USHORT ModeIdIndex)
+SiS_SetCRT1FIFO_630(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                    unsigned short RefreshRateTableIndex)
 {
-  USHORT data=0, VCLK=0, index=0;
+   unsigned short  ThresholdLow = 0;
+   unsigned short  i, data, VCLK, MCLK16, colorth = 0;
+   unsigned int    templ, datal;
+   const unsigned char *queuedata = NULL;
+   static const unsigned char FQBQData[21] = {
+               0x01,0x21,0x41,0x61,0x81,
+               0x31,0x51,0x71,0x91,0xb1,
+               0x00,0x20,0x40,0x60,0x80,
+               0x30,0x50,0x70,0x90,0xb0,
+               0xff
+   };
+   static const unsigned char FQBQData730[16] = {
+               0x34,0x74,0xb4,
+               0x23,0x63,0xa3,
+               0x12,0x52,0x92,
+               0x01,0x41,0x81,
+               0x00,0x40,0x80,
+               0xff
+   };
+   static const unsigned short colortharray[6] = {
+               1, 1, 2, 2, 3, 4
+   };
+
+   i = 0;
 
-  if(ModeNo > 0x13) {
-     if(SiS_Pr->UseCustomMode) {
-        VCLK = SiS_Pr->CSRClock;
-     } else {
-        index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
-                             RefreshRateTableIndex,HwInfo);
-        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
-     }
-  }
+   if(ModeNo > 0x13) {
+
+      /* Get VCLK  */
+      if(SiS_Pr->UseCustomMode) {
+        VCLK = SiS_Pr->CSRClock;
+      } else {
+        data = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWide);
+        VCLK = SiS_Pr->SiS_VCLKData[data].CLOCK;
+      }
 
-  if(HwInfo->jChipType < SIS_315H) {
+      /* Get MCLK * 16 */
+      data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A) & 0x07;
+      MCLK16 = SiS_Pr->SiS_MCLKData_0[data].CLOCK * 16;
 
-     if(VCLK > 150) data |= 0x80;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
+      /* Get half colordepth */
+      colorth = colortharray[(SiS_Pr->SiS_ModeType - ModeEGA)];
 
-     data = 0x00;
-     if(VCLK >= 150) data |= 0x08;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+      if(SiS_Pr->ChipType == SIS_730) {
+        queuedata = &FQBQData730[0];
+      } else {
+        queuedata = &FQBQData[0];
+      }
 
-  } else {
+      do {
+        templ = SiS_CalcDelay2(SiS_Pr, queuedata[i]) * VCLK * colorth;
 
-     if(VCLK >= 166) data |= 0x0c;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+        datal = templ % MCLK16;
+        templ = (templ / MCLK16) + 1;
+        if(datal) templ++;
 
-     if(VCLK >= 166) {
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
-     }
-  }
+        if(templ > 0x13) {
+           if(queuedata[i + 1] == 0xFF) {
+              ThresholdLow = 0x13;
+              break;
+           }
+           i++;
+        } else {
+           ThresholdLow = templ;
+           break;
+        }
+      } while(queuedata[i] != 0xFF);
 
-  /* DAC speed */
-  if(HwInfo->jChipType >= SIS_661) {
+   } else {
 
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
+      if(SiS_Pr->ChipType != SIS_730) i = 9;
+      ThresholdLow = 0x02;
 
-  } else {
+   }
 
-     data = 0x03;
-     if((VCLK >= 135) && (VCLK < 160))      data = 0x02;
-     else if((VCLK >= 160) && (VCLK < 260)) data = 0x01;
-     else if(VCLK >= 260)                   data = 0x00;
+   /* Write CRT/CPU threshold low, CRT/Engine threshold high */
+   data = ((ThresholdLow & 0x0f) << 4) | 0x0f;
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,data);
 
-     if(HwInfo->jChipType == SIS_540) {
-        if((VCLK == 203) || (VCLK < 234))   data = 0x02;
-     }
+   data = (ThresholdLow & 0x10) << 1;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xDF,data);
 
-     if(HwInfo->jChipType < SIS_315H) {
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
-     } else {
-        if(HwInfo->jChipType > SIS_315PRO) {
-           if(ModeNo > 0x13) data &= 0xfc;
-        }
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
-     }
+   /* What is this? */
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x3B,0x09);
 
-  }
-}
+   /* Write CRT/CPU threshold high (gap = 3) */
+   data = ThresholdLow + 3;
+   if(data > 0x0f) data = 0x0f;
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x09,0x80,data);
 
-static void
-SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                    USHORT ModeNo,USHORT ModeIdIndex,USHORT RefreshRateTableIndex)
-{
-  USHORT data,infoflag=0,modeflag;
-  USHORT resindex,xres;
-#ifdef SIS315H
-  USHORT data2,data3;
-  ULONG  longdata;
-  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
+  /* Write foreground and background queue */
+#ifdef SIS_LINUX_KERNEL
+   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
+#else
+   templ = pciReadLong(0x00000000, 0x50);
 #endif
 
-  if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-     infoflag = SiS_Pr->CInfoFlag;
-     xres = SiS_Pr->CHDisplay;
-  } else {
-     resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
-     if(ModeNo > 0x13) {
-       modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-       infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-       xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
-     } else {
-       modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-       xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
-     }
-  }
-
-  /* Disable DPMS */
-  SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
-
-  data = 0;
-  if(ModeNo > 0x13) {
-     if(SiS_Pr->SiS_ModeType > ModeEGA) {
-        data |= 0x02;
-        data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
-     }
-     if(infoflag & InterlaceMode) data |= 0x20;
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
-
-  if(HwInfo->jChipType != SIS_300) {
-     data = 0;
-     if(infoflag & InterlaceMode) {
-        if(xres <= 800)       data = 0x0020;
-        else if(xres <= 1024) data = 0x0035;
-        else                  data = 0x0048;
-     }
-     SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,(data & 0xFF));
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,(data >> 8));
-  }
-
-  if(modeflag & HalfDCLK) {
-     SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
-  }
-
-  data = 0;
-  if(modeflag & LineCompareOff) data = 0x08;
-  if(HwInfo->jChipType == SIS_300) {
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
-  } else {
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
-     if(SiS_Pr->SiS_ModeType == ModeEGA) {
-        if(ModeNo > 0x13) {
-          SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x0F,0x40);
-        }
-     }
-  }
-
-  if(HwInfo->jChipType >= SIS_661) {
-     SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
-  }
+   if(SiS_Pr->ChipType == SIS_730) {
 
-#ifdef SIS315H
-  if(HwInfo->jChipType == SIS_315PRO) {
-
-     data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
-     data = SiS_Pr->SiS_SR15[2][data];
-     if(SiS_Pr->SiS_ModeType == ModeText) {
-        data &= 0xc7;
-     } else {
-        data2 = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,
-                              RefreshRateTableIndex,HwInfo);
-       data2 >>= 1;
-       if(infoflag & InterlaceMode) data2 >>= 1;
-       data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
-       if(!data3) data3++;
-       data2 /= data3;
-       if(data2 >= 0x50) {
-          data &= 0x0f;
-          data |= 0x50;
-       }
-     }
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-
-  } else if( (HwInfo->jChipType == SIS_330) ||
-             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) {
-
-     data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
-     if(HwInfo->jChipType == SIS_330) {
-        data = SiS_Pr->SiS_SR15[2][data];
-     } else {
-        if(SiS_Pr->SiS_ROMNew)             data = ROMAddr[0xf6];
-        else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
-       else                        data = 0xba;
-     }
-     if(SiS_Pr->SiS_ModeType <= ModeEGA) {
-        data &= 0xc7;
-     } else {
-        if(SiS_Pr->UseCustomMode) {
-          data2 = SiS_Pr->CSRClock;
-       } else {
-           data2 = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,
-                                   RefreshRateTableIndex,HwInfo);
-           data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
-       }
+      templ &= 0xfffff9ff;
+      templ |= ((queuedata[i] & 0xc0) << 3);
 
-       data3 = SiS_GetColorDepth(SiS_Pr,ModeNo,ModeIdIndex) >> 1;
-       if(data3) data2 *= data3;
-
-       longdata = SiS_GetMCLK(SiS_Pr, HwInfo) * 1024;
-
-       data2 = longdata / data2;
-
-       if(HwInfo->jChipType == SIS_330) {
-          if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
-              if     (data2 >= 0x19c) data = 0xba;
-             else if(data2 >= 0x140) data = 0x7a;
-             else if(data2 >= 0x101) data = 0x3a;
-             else if(data2 >= 0xf5)  data = 0x32;
-             else if(data2 >= 0xe2)  data = 0x2a;
-             else if(data2 >= 0xc4)  data = 0x22;
-             else if(data2 >= 0xac)  data = 0x1a;
-             else if(data2 >= 0x9e)  data = 0x12;
-             else if(data2 >= 0x8e)  data = 0x0a;
-             else                    data = 0x02;
-          } else {
-             if(data2 >= 0x127)      data = 0xba;
-             else                    data = 0x7a;
-          }
-       } else {  /* 760+LFB */
-          if     (data2 >= 0x190) data = 0xba;
-          else if(data2 >= 0xff)  data = 0x7a;
-          else if(data2 >= 0xd3)  data = 0x3a;
-          else if(data2 >= 0xa9)  data = 0x1a;
-          else if(data2 >= 0x93)  data = 0x0a;
-          else                    data = 0x02;
-       }
-     }
-     SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
-  } else if(HwInfo->jChipType == SIS_340) {
-     /* TODO */
-  }
+   } else {
+
+      templ &= 0xf0ffffff;
+      if( (ModeNo <= 0x13) &&
+          (SiS_Pr->ChipType == SIS_630) &&
+         (SiS_Pr->ChipRevision >= 0x30) ) {
+        templ |= 0x0b000000;
+      } else {
+         templ |= ((queuedata[i] & 0xf0) << 20);
+      }
+
+   }
+
+#ifdef SIS_LINUX_KERNEL
+   sisfb_write_nbridge_pci_dword(SiS_Pr, 0x50, templ);
+   templ = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xA0);
+#else
+   pciWriteLong(0x00000000, 0x50, templ);
+   templ = pciReadLong(0x00000000, 0xA0);
 #endif
 
-  data = 0x60;
-  if(SiS_Pr->SiS_ModeType != ModeText) {
-     data ^= 0x60;
-     if(SiS_Pr->SiS_ModeType != ModeEGA) {
-        data ^= 0xA0;
-     }
-  }
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
+   /* GUI grant timer (PCI config 0xA3) */
+   if(SiS_Pr->ChipType == SIS_730) {
 
-  SiS_SetVCLKState(SiS_Pr, HwInfo, ModeNo, RefreshRateTableIndex, ModeIdIndex);
+      templ &= 0x00ffffff;
+      datal = queuedata[i] << 8;
+      templ |= (((datal & 0x0f00) | ((datal & 0x3000) >> 8)) << 20);
 
-#ifdef SIS315H
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
-     } else {
-        SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
-     }
-  }
+   } else {
+
+      templ &= 0xf0ffffff;
+      templ |= ((queuedata[i] & 0x0f) << 24);
+
+   }
+
+#ifdef SIS_LINUX_KERNEL
+   sisfb_write_nbridge_pci_dword(SiS_Pr, 0xA0, templ);
+#else
+   pciWriteLong(0x00000000, 0xA0, templ);
 #endif
 }
+#endif /* SIS300 */
+
+#ifdef SIS315H
+static void
+SiS_SetCRT1FIFO_310(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short modeflag;
+
+   /* disable auto-threshold */
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x3D,0xFE);
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0xAE);
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x09,0xF0);
+   if(ModeNo > 0x13) {
+      if(SiS_Pr->ChipType >= XGI_20) {
+        SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+      } else if(SiS_Pr->ChipType >= SIS_661) {
+        if(!(modeflag & HalfDCLK)) {
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+           SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+        }
+      } else {
+        if((!(modeflag & DoubleScanMode)) || (!(modeflag & HalfDCLK))) {
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x08,0x34);
+           SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x3D,0x01);
+        }
+      }
+   }
+}
+#endif
 
 /*********************************************/
-/*                 LOAD DAC                  */
+/*              MODE REGISTERS               */
 /*********************************************/
 
-#if 0
 static void
-SiS_ClearDAC(SiS_Private *SiS_Pr, ULONG port)
+SiS_SetVCLKState(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short RefreshRateTableIndex, unsigned short ModeIdIndex)
+{
+   unsigned short data = 0, VCLK = 0, index = 0;
+
+   if(ModeNo > 0x13) {
+      if(SiS_Pr->UseCustomMode) {
+         VCLK = SiS_Pr->CSRClock;
+      } else {
+         index = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+         VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
+      }
+   }
+
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+      if(VCLK > 150) data |= 0x80;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0x7B,data);
+
+      data = 0x00;
+      if(VCLK >= 150) data |= 0x08;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xF7,data);
+#endif
+   } else if(SiS_Pr->ChipType < XGI_20) {
+#ifdef SIS315H
+      if(VCLK >= 166) data |= 0x0c;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+
+      if(VCLK >= 166) {
+         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1f,0xe7);
+      }
+#endif
+   } else {
+#ifdef SIS315H
+      if(VCLK >= 200) data |= 0x0c;
+      if(SiS_Pr->ChipType == XGI_20) data &= ~0x04;
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x32,0xf3,data);
+      if(SiS_Pr->ChipType != XGI_20) {
+         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xe7;
+        if(VCLK < 200) data |= 0x10;
+        SiS_SetReg(SiS_Pr->SiS_P3c4,0x1f,data);
+      }
+#endif
+   }
+
+   /* DAC speed */
+   if(SiS_Pr->ChipType >= SIS_661) {
+
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xE8,0x10);
+
+   } else {
+
+      data = 0x03;
+      if(VCLK >= 260)      data = 0x00;
+      else if(VCLK >= 160) data = 0x01;
+      else if(VCLK >= 135) data = 0x02;
+
+      if(SiS_Pr->ChipType == SIS_540) {
+         if((VCLK == 203) || (VCLK < 234)) data = 0x02;
+      }
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xFC,data);
+      } else {
+         if(SiS_Pr->ChipType > SIS_315PRO) {
+            if(ModeNo > 0x13) data &= 0xfc;
+         }
+         SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x07,0xF8,data);
+      }
+
+   }
+}
+
+static void
+SiS_SetCRT1ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short RRTI)
+{
+   unsigned short data, infoflag = 0, modeflag, resindex;
+#ifdef SIS315H
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+   unsigned short data2, data3;
+#endif
+
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+   } else {
+      resindex = SiS_GetResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+      if(ModeNo > 0x13) {
+        infoflag = SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag;
+      }
+   }
+
+   /* Disable DPMS */
+   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1F,0x3F);
+
+   data = 0;
+   if(ModeNo > 0x13) {
+      if(SiS_Pr->SiS_ModeType > ModeEGA) {
+         data |= 0x02;
+         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
+      }
+      if(infoflag & InterlaceMode) data |= 0x20;
+   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x06,0xC0,data);
+
+   if(SiS_Pr->ChipType != SIS_300) {
+      data = 0;
+      if(infoflag & InterlaceMode) {
+        /* data = (Hsync / 8) - ((Htotal / 8) / 2) + 3 */
+        int hrs = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x04) |
+                   ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2)) - 3;
+        int hto = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x00) |
+                   ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0x03) << 8)) + 5;
+        data = hrs - (hto >> 1) + 3;
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x19,data);
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x1a,0xFC,((data >> 8) & 0x03));
+   }
+
+   if(modeflag & HalfDCLK) {
+      SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x01,0x08);
+   }
+
+   data = 0;
+   if(modeflag & LineCompareOff) data = 0x08;
+   if(SiS_Pr->ChipType == SIS_300) {
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xF7,data);
+   } else {
+      if(SiS_Pr->ChipType >= XGI_20) data |= 0x20;
+      if(SiS_Pr->SiS_ModeType == ModeEGA) {
+        if(ModeNo > 0x13) {
+           data |= 0x40;
+        }
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0F,0xB7,data);
+   }
+
+#ifdef SIS315H
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x31,0xfb);
+   }
+
+   if(SiS_Pr->ChipType == SIS_315PRO) {
+
+      data = SiS_Pr->SiS_SR15[(2 * 4) + SiS_Get310DRAMType(SiS_Pr)];
+      if(SiS_Pr->SiS_ModeType == ModeText) {
+        data &= 0xc7;
+      } else {
+        data2 = SiS_GetOffset(SiS_Pr, ModeNo, ModeIdIndex, RRTI) >> 1;
+        if(infoflag & InterlaceMode) data2 >>= 1;
+        data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+        if(data3) data2 /= data3;
+        if(data2 >= 0x50) {
+           data &= 0x0f;
+           data |= 0x50;
+        }
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+   } else if((SiS_Pr->ChipType == SIS_330) || (SiS_Pr->SiS_SysFlags & SF_760LFB)) {
+
+      data = SiS_Get310DRAMType(SiS_Pr);
+      if(SiS_Pr->ChipType == SIS_330) {
+        data = SiS_Pr->SiS_SR15[(2 * 4) + data];
+      } else {
+        if(SiS_Pr->SiS_ROMNew)      data = ROMAddr[0xf6];
+        else if(SiS_Pr->SiS_UseROM) data = ROMAddr[0x100 + data];
+        else                        data = 0xba;
+      }
+      if(SiS_Pr->SiS_ModeType <= ModeEGA) {
+        data &= 0xc7;
+      } else {
+        if(SiS_Pr->UseCustomMode) {
+           data2 = SiS_Pr->CSRClock;
+        } else {
+           data2 = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
+           data2 = SiS_Pr->SiS_VCLKData[data2].CLOCK;
+        }
+
+        data3 = SiS_GetColorDepth(SiS_Pr, ModeNo, ModeIdIndex) >> 1;
+        if(data3) data2 *= data3;
+
+        data2 = ((unsigned int)(SiS_GetMCLK(SiS_Pr) * 1024)) / data2;
+
+        if(SiS_Pr->ChipType == SIS_330) {
+           if(SiS_Pr->SiS_ModeType != Mode16Bpp) {
+              if     (data2 >= 0x19c) data = 0xba;
+              else if(data2 >= 0x140) data = 0x7a;
+              else if(data2 >= 0x101) data = 0x3a;
+              else if(data2 >= 0xf5)  data = 0x32;
+              else if(data2 >= 0xe2)  data = 0x2a;
+              else if(data2 >= 0xc4)  data = 0x22;
+              else if(data2 >= 0xac)  data = 0x1a;
+              else if(data2 >= 0x9e)  data = 0x12;
+              else if(data2 >= 0x8e)  data = 0x0a;
+              else                    data = 0x02;
+           } else {
+              if(data2 >= 0x127)      data = 0xba;
+              else                    data = 0x7a;
+           }
+        } else {  /* 76x+LFB */
+           if     (data2 >= 0x190) data = 0xba;
+           else if(data2 >= 0xff)  data = 0x7a;
+           else if(data2 >= 0xd3)  data = 0x3a;
+           else if(data2 >= 0xa9)  data = 0x1a;
+           else if(data2 >= 0x93)  data = 0x0a;
+           else                    data = 0x02;
+        }
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
+
+   }
+      /* XGI: Nothing. */
+      /* TODO: Check SiS340 */
+#endif
+
+   data = 0x60;
+   if(SiS_Pr->SiS_ModeType != ModeText) {
+      data ^= 0x60;
+      if(SiS_Pr->SiS_ModeType != ModeEGA) {
+         data ^= 0xA0;
+      }
+   }
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x21,0x1F,data);
+
+   SiS_SetVCLKState(SiS_Pr, ModeNo, RRTI, ModeIdIndex);
+
+#ifdef SIS315H
+   if(((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) ||
+       (SiS_Pr->ChipType == XGI_40)) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x2c);
+      } else {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x6c);
+      }
+   } else if(SiS_Pr->ChipType == XGI_20) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x33);
+      } else {
+         SiS_SetReg(SiS_Pr->SiS_P3d4,0x52,0x73);
+      }
+      SiS_SetReg(SiS_Pr->SiS_P3d4,0x51,0x02);
+   }
+#endif
+}
+
+#ifdef SIS315H
+static void
+SiS_SetupDualChip(struct SiS_Private *SiS_Pr)
 {
+#if 0
+   /* TODO: Find out about IOAddress2 */
+   SISIOADDRESS P2_3c2 = SiS_Pr->IOAddress2 + 0x12;
+   SISIOADDRESS P2_3c4 = SiS_Pr->IOAddress2 + 0x14;
+   SISIOADDRESS P2_3ce = SiS_Pr->IOAddress2 + 0x1e;
    int i;
 
-   OutPortByte(port, 0);
-   port++;
-   for (i=0; i < (256 * 3); i++) {
-      OutPortByte(port, 0);
+   if((SiS_Pr->ChipRevision != 0) ||
+      (!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x3a) & 0x04)))
+      return;
+
+   for(i = 0; i <= 4; i++) {                                   /* SR00 - SR04 */
+      SiS_SetReg(P2_3c4,i,SiS_GetReg(SiS_Pr->SiS_P3c4,i));
    }
+   for(i = 0; i <= 8; i++) {                                   /* GR00 - GR08 */
+      SiS_SetReg(P2_3ce,i,SiS_GetReg(SiS_Pr->SiS_P3ce,i));
+   }
+   SiS_SetReg(P2_3c4,0x05,0x86);
+   SiS_SetReg(P2_3c4,0x06,SiS_GetReg(SiS_Pr->SiS_P3c4,0x06));  /* SR06 */
+   SiS_SetReg(P2_3c4,0x21,SiS_GetReg(SiS_Pr->SiS_P3c4,0x21));  /* SR21 */
+   SiS_SetRegByte(P2_3c2,SiS_GetRegByte(SiS_Pr->SiS_P3cc));    /* MISC */
+   SiS_SetReg(P2_3c4,0x05,0x00);
+#endif
 }
 #endif
 
+/*********************************************/
+/*                 LOAD DAC                  */
+/*********************************************/
+
 static void
-SiS_WriteDAC(SiS_Private *SiS_Pr, SISIOADDRESS DACData, USHORT shiftflag,
-             USHORT dl, USHORT ah, USHORT al, USHORT dh)
+SiS_WriteDAC(struct SiS_Private *SiS_Pr, SISIOADDRESS DACData, unsigned short shiftflag,
+             unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh)
 {
-  USHORT temp,bh,bl;
-
-  bh = ah;
-  bl = al;
-  if(dl != 0) {
-     temp = bh;
-     bh = dh;
-     dh = temp;
-     if(dl == 1) {
-        temp = bl;
-        bl = dh;
-        dh = temp;
-     } else {
-        temp = bl;
-        bl = bh;
-        bh = temp;
-     }
-  }
-  if(shiftflag) {
-     dh <<= 2;
-     bh <<= 2;
-     bl <<= 2;
-  }
-  SiS_SetRegByte(DACData,(USHORT)dh);
-  SiS_SetRegByte(DACData,(USHORT)bh);
-  SiS_SetRegByte(DACData,(USHORT)bl);
+   unsigned short d1, d2, d3;
+
+   switch(dl) {
+   case  0: d1 = dh; d2 = ah; d3 = al; break;
+   case  1: d1 = ah; d2 = al; d3 = dh; break;
+   default: d1 = al; d2 = dh; d3 = ah;
+   }
+   SiS_SetRegByte(DACData, (d1 << shiftflag));
+   SiS_SetRegByte(DACData, (d2 << shiftflag));
+   SiS_SetRegByte(DACData, (d3 << shiftflag));
 }
 
 void
-SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-            USHORT ModeNo, USHORT ModeIdIndex)
+SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-   USHORT data,data2;
-   USHORT time,i,j,k,m,n,o;
-   USHORT si,di,bx,dl,al,ah,dh;
-   USHORT shiftflag;
+   unsigned short data, data2, time, i, j, k, m, n, o;
+   unsigned short si, di, bx, sf;
    SISIOADDRESS DACAddr, DACData;
-   const USHORT *table = NULL;
+   const unsigned char *table = NULL;
 
-   if(ModeNo <= 0x13) {
-      data = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-   } else {
-      if(SiS_Pr->UseCustomMode) {
-        data = SiS_Pr->CModeFlag;
-      } else {
-         data = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-      }
-   }
+   data = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex) & DACInfoFlag;
 
-   data &= DACInfoFlag;
-   time = 64;
-   if(data == 0x00) table = SiS_MDA_DAC;
-   if(data == 0x08) table = SiS_CGA_DAC;
-   if(data == 0x10) table = SiS_EGA_DAC;
-   if(data == 0x18) {
+   j = time = 64;
+   if(data == 0x00)      table = SiS_MDA_DAC;
+   else if(data == 0x08) table = SiS_CGA_DAC;
+   else if(data == 0x10) table = SiS_EGA_DAC;
+   else if(data == 0x18) {
+      j = 16;
       time = 256;
       table = SiS_VGA_DAC;
    }
-   if(time == 256) j = 16;
-   else            j = time;
 
    if( ( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&        /* 301B-DH LCD */
          (SiS_Pr->SiS_VBType & VB_NoLCD) )        ||
        (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)       ||   /* LCDA */
        (!(SiS_Pr->SiS_SetFlag & ProgrammingCRT2)) ) {  /* Programming CRT1 */
+      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
       DACAddr = SiS_Pr->SiS_P3c8;
       DACData = SiS_Pr->SiS_P3c9;
-      shiftflag = 0;
-      SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
+      sf = 0;
    } else {
-      shiftflag = 1;
       DACAddr = SiS_Pr->SiS_Part5Port;
       DACData = SiS_Pr->SiS_Part5Port + 1;
+      sf = 2;
    }
 
    SiS_SetRegByte(DACAddr,0x00);
 
-   for(i=0; i<j; i++) {
+   for(i = 0; i < j; i++) {
       data = table[i];
-      for(k=0; k<3; k++) {
+      for(k = 0; k < 3; k++) {
        data2 = 0;
-       if(data & 0x01) data2 = 0x2A;
+       if(data & 0x01) data2 += 0x2A;
        if(data & 0x02) data2 += 0x15;
-       if(shiftflag) data2 <<= 2;
-       SiS_SetRegByte(DACData, data2);
+       SiS_SetRegByte(DACData, (data2 << sf));
        data >>= 2;
       }
    }
 
    if(time == 256) {
       for(i = 16; i < 32; i++) {
-        data = table[i];
-        if(shiftflag) data <<= 2;
+        data = table[i] << sf;
         for(k = 0; k < 3; k++) SiS_SetRegByte(DACData, data);
       }
       si = 32;
       for(m = 0; m < 9; m++) {
-         di = si;
-         bx = si + 4;
-         dl = 0;
-         for(n = 0; n < 3; n++) {
-           for(o = 0; o < 5; o++) {
-              dh = table[si];
-              ah = table[di];
-              al = table[bx];
+        di = si;
+        bx = si + 4;
+        for(n = 0; n < 3; n++) {
+           for(o = 0; o < 5; o++) {
+              SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[bx], table[si]);
               si++;
-              SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh);
            }
            si -= 2;
            for(o = 0; o < 3; o++) {
-              dh = table[bx];
-              ah = table[di];
-              al = table[si];
+              SiS_WriteDAC(SiS_Pr, DACData, sf, n, table[di], table[si], table[bx]);
               si--;
-              SiS_WriteDAC(SiS_Pr, DACData, shiftflag, dl, ah, al, dh);
            }
-           dl++;
         }            /* for n < 3 */
         si += 5;
       }               /* for m < 9 */
@@ -3241,89 +2972,114 @@ SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 /*********************************************/
 
 static void
-SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                 USHORT ModeNo, USHORT ModeIdIndex)
+SiS_SetCRT1Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  USHORT  StandTableIndex,RefreshRateTableIndex;
-
-  SiS_Pr->SiS_CRT1Mode = ModeNo;
-  StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
-  if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-     if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
-        SiS_DisableBridge(SiS_Pr, HwInfo);
-     }
-  }
-
-  SiS_ResetSegmentRegisters(SiS_Pr, HwInfo);
-
-  SiS_SetSeqRegs(SiS_Pr, StandTableIndex, HwInfo);
-  SiS_SetMiscRegs(SiS_Pr, StandTableIndex, HwInfo);
-  SiS_SetCRTCRegs(SiS_Pr, HwInfo, StandTableIndex);
-  SiS_SetATTRegs(SiS_Pr, StandTableIndex, HwInfo);
-  SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
-  SiS_ClearExt1Regs(SiS_Pr, HwInfo, ModeNo);
-  SiS_ResetCRT1VCLK(SiS_Pr, HwInfo);
-
-  SiS_Pr->SiS_SelectCRT2Rate = 0;
-  SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-
-#ifdef LINUX_XF86
-  xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
+   unsigned short StandTableIndex, RefreshRateTableIndex;
+
+   SiS_Pr->SiS_CRT1Mode = ModeNo;
+
+   StandTableIndex = SiS_GetModePtr(SiS_Pr, ModeNo, ModeIdIndex);
+
+   if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2)) {
+         SiS_DisableBridge(SiS_Pr);
+      }
+   }
+
+   SiS_ResetSegmentRegisters(SiS_Pr);
+
+   SiS_SetSeqRegs(SiS_Pr, StandTableIndex);
+   SiS_SetMiscRegs(SiS_Pr, StandTableIndex);
+   SiS_SetCRTCRegs(SiS_Pr, StandTableIndex);
+   SiS_SetATTRegs(SiS_Pr, StandTableIndex);
+   SiS_SetGRCRegs(SiS_Pr, StandTableIndex);
+   SiS_ClearExt1Regs(SiS_Pr, ModeNo);
+   SiS_ResetCRT1VCLK(SiS_Pr);
+
+   SiS_Pr->SiS_SelectCRT2Rate = 0;
+   SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+
+#ifdef SIS_XORG_XF86
+   xf86DrvMsgVerb(0, X_PROBED, 4, "(init: VBType=0x%04x, VBInfo=0x%04x)\n",
                     SiS_Pr->SiS_VBType, SiS_Pr->SiS_VBInfo);
 #endif
 
-  if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
-     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-     }
-  }
+   if(SiS_Pr->SiS_VBInfo & SetSimuScanMode) {
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+         SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+      }
+   }
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-  }
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+      SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+   }
 
-  RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
 
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-     SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
-  }
+   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+      SiS_Pr->SiS_SetFlag &= ~ProgrammingCRT2;
+   }
 
-  if(RefreshRateTableIndex != 0xFFFF) {
-     SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
-     SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-     SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-     SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
-  }
+   if(RefreshRateTableIndex != 0xFFFF) {
+      SiS_SetCRT1Sync(SiS_Pr, RefreshRateTableIndex);
+      SiS_SetCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      SiS_SetCRT1Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      SiS_SetCRT1VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+   }
 
+   switch(SiS_Pr->ChipType) {
 #ifdef SIS300
-  if(HwInfo->jChipType == SIS_300) {
-     SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo,HwInfo,RefreshRateTableIndex);
-  } else if((HwInfo->jChipType == SIS_630) ||
-            (HwInfo->jChipType == SIS_730) ||
-            (HwInfo->jChipType == SIS_540)) {
-     SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, HwInfo, RefreshRateTableIndex);
-  }
+   case SIS_300:
+      SiS_SetCRT1FIFO_300(SiS_Pr, ModeNo, RefreshRateTableIndex);
+      break;
+   case SIS_540:
+   case SIS_630:
+   case SIS_730:
+      SiS_SetCRT1FIFO_630(SiS_Pr, ModeNo, RefreshRateTableIndex);
+      break;
 #endif
+   default:
 #ifdef SIS315H
-  if(HwInfo->jChipType >= SIS_315H) {
-     SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-  }
+      if(SiS_Pr->ChipType == XGI_20) {
+         unsigned char sr2b = 0, sr2c = 0;
+         switch(ModeNo) {
+        case 0x00:
+        case 0x01: sr2b = 0x4e; sr2c = 0xe9; break;
+        case 0x04:
+        case 0x05:
+        case 0x0d: sr2b = 0x1b; sr2c = 0xe3; break;
+        }
+        if(sr2b) {
+            SiS_SetReg(SiS_Pr->SiS_P3c4,0x2b,sr2b);
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x2c,sr2c);
+           SiS_SetRegByte(SiS_Pr->SiS_P3c2,(SiS_GetRegByte(SiS_Pr->SiS_P3cc) | 0x0c));
+        }
+      }
+      SiS_SetCRT1FIFO_310(SiS_Pr, ModeNo, ModeIdIndex);
 #endif
+      break;
+   }
+
+   SiS_SetCRT1ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 
-  SiS_SetCRT1ModeRegs(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+#ifdef SIS315H
+   if(SiS_Pr->ChipType == XGI_40) {
+      SiS_SetupDualChip(SiS_Pr);
+   }
+#endif
 
-  SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+   SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
 
-#ifdef LINUX_KERNEL
-  if(SiS_Pr->SiS_flag_clearbuffer) {
-     SiS_ClearBuffer(SiS_Pr,HwInfo,ModeNo);
-  }
+#ifdef SIS_LINUX_KERNEL
+   if(SiS_Pr->SiS_flag_clearbuffer) {
+      SiS_ClearBuffer(SiS_Pr, ModeNo);
+   }
 #endif
 
-  if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
-     SiS_WaitRetrace1(SiS_Pr);
-     SiS_DisplayOn(SiS_Pr);
-  }
+   if(!(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA))) {
+      SiS_WaitRetrace1(SiS_Pr);
+      SiS_DisplayOn(SiS_Pr);
+   }
 }
 
 /*********************************************/
@@ -3331,33 +3087,62 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 /*********************************************/
 
 static void
-SiS_ResetVB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_InitVB(struct SiS_Private *SiS_Pr)
+{
+   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+
+   SiS_Pr->Init_P4_0E = 0;
+   if(SiS_Pr->SiS_ROMNew) {
+      SiS_Pr->Init_P4_0E = ROMAddr[0x82];
+   } else if(SiS_Pr->ChipType >= XGI_40) {
+      if(SiS_Pr->SiS_XGIROM) {
+         SiS_Pr->Init_P4_0E = ROMAddr[0x80];
+      }
+   }
+}
+
+static void
+SiS_ResetVB(struct SiS_Private *SiS_Pr)
 {
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
-   USHORT temp;
+#ifdef SIS315H
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp;
 
    /* VB programming clock */
    if(SiS_Pr->SiS_UseROM) {
-      if(HwInfo->jChipType < SIS_330) {
-         temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
+      if(SiS_Pr->ChipType < SIS_330) {
+        temp = ROMAddr[VB310Data_1_2_Offset] | 0x40;
         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
-      } else if(HwInfo->jChipType >= SIS_661) {
-         temp = ROMAddr[0x7e] | 0x40;
-         if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
+      } else if(SiS_Pr->ChipType >= SIS_661 && SiS_Pr->ChipType < XGI_20) {
+        temp = ROMAddr[0x7e] | 0x40;
+        if(SiS_Pr->SiS_ROMNew) temp = ROMAddr[0x80] | 0x40;
         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
       }
+   } else if(SiS_Pr->ChipType >= XGI_40) {
+      temp = 0x40;
+      if(SiS_Pr->SiS_XGIROM) temp |= ROMAddr[0x7e];
+      /* Can we do this on any chipset? */
+      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,temp);
    }
+#endif
 }
 
 /*********************************************/
-/*         HELPER: SET VIDEO REGISTERS       */
+/*    HELPER: SET VIDEO/CAPTURE REGISTERS    */
 /*********************************************/
 
 static void
-SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_StrangeStuff(struct SiS_Private *SiS_Pr)
 {
-   if((IS_SIS651) || (IS_SISM650)) {
+   /* SiS65x and XGI set up some sort of "lock mode" for text
+    * which locks CRT2 in some way to CRT1 timing. Disable
+    * this here.
+    */
+#ifdef SIS315H
+   if((IS_SIS651) || (IS_SISM650) ||
+      SiS_Pr->ChipType == SIS_340 ||
+      SiS_Pr->ChipType == XGI_40) {
       SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x3f, 0x00);   /* Fiddle with capture regs */
       SiS_SetReg(SiS_Pr->SiS_VidCapt, 0x00, 0x00);
       SiS_SetReg(SiS_Pr->SiS_VidPlay, 0x00, 0x86);   /* (BIOS does NOT unlock) */
@@ -3365,49 +3150,99 @@ SiS_StrangeStuff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
       SiS_SetRegAND(SiS_Pr->SiS_VidPlay, 0x3f, 0xef);
    }
    /* !!! This does not support modes < 0x13 !!! */
+#endif
+}
+
+/*********************************************/
+/*     HELPER: SET AGP TIMING FOR SiS760     */
+/*********************************************/
+
+static void
+SiS_Handle760(struct SiS_Private *SiS_Pr)
+{
+#ifdef SIS315H
+   unsigned int somebase;
+   unsigned char temp1, temp2, temp3;
+
+   if( (SiS_Pr->ChipType != SIS_760)                         ||
+       ((SiS_GetReg(SiS_Pr->SiS_P3d4, 0x5c) & 0xf8) != 0x80) ||
+       (!(SiS_Pr->SiS_SysFlags & SF_760LFB))                 ||
+       (!(SiS_Pr->SiS_SysFlags & SF_760UMA)) )
+      return;
+
+#ifdef SIS_LINUX_KERNEL
+   somebase = sisfb_read_mio_pci_word(SiS_Pr, 0x74);
+#else
+   somebase = pciReadWord(0x00001000, 0x74);
+#endif
+   somebase &= 0xffff;
+
+   if(somebase == 0) return;
+
+   temp3 = SiS_GetRegByte((somebase + 0x85)) & 0xb7;
+
+   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40) {
+      temp1 = 0x21;
+      temp2 = 0x03;
+      temp3 |= 0x08;
+   } else {
+      temp1 = 0x25;
+      temp2 = 0x0b;
+   }
+
+#ifdef SIS_LINUX_KERNEL
+   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x7e, temp1);
+   sisfb_write_nbridge_pci_byte(SiS_Pr, 0x8d, temp2);
+#else
+   pciWriteByte(0x00000000, 0x7e, temp1);
+   pciWriteByte(0x00000000, 0x8d, temp2);
+#endif
+
+   SiS_SetRegByte((somebase + 0x85), temp3);
+#endif
 }
 
 /*********************************************/
-/*         XFree86: SET SCREEN PITCH         */
+/*      X.org/XFree86: SET SCREEN PITCH      */
 /*********************************************/
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 static void
-SiS_SetPitchCRT1(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitchCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
 {
    SISPtr pSiS = SISPTR(pScrn);
-   UShort HDisplay = pSiS->scrnPitch >> 3;
+   unsigned short HDisplay = pSiS->scrnPitch >> 3;
 
    SiS_SetReg(SiS_Pr->SiS_P3d4,0x13,(HDisplay & 0xFF));
-   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay>>8));
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0xF0,(HDisplay >> 8));
 }
 
 static void
-SiS_SetPitchCRT2(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitchCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
 {
    SISPtr pSiS = SISPTR(pScrn);
-   UShort HDisplay = pSiS->scrnPitch2 >> 3;
+   unsigned short HDisplay = pSiS->scrnPitch2 >> 3;
 
     /* Unlock CRT2 */
    if(pSiS->VGAEngine == SIS_315_VGA)
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2F, 0x01);
    else
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
+      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24, 0x01);
 
    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(HDisplay & 0xFF));
    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0xF0,(HDisplay >> 8));
 }
 
 static void
-SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
+SiS_SetPitch(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
 {
    SISPtr pSiS = SISPTR(pScrn);
    BOOLEAN isslavemode = FALSE;
 
-   if( (pSiS->VBFlags & VB_VIDEOBRIDGE) &&
+   if( (pSiS->VBFlags2 & VB2_VIDEOBRIDGE) &&
        ( ((pSiS->VGAEngine == SIS_300_VGA) &&
-          (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
-         ((pSiS->VGAEngine == SIS_315_VGA) &&
+         (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0xa0) == 0x20) ||
+        ((pSiS->VGAEngine == SIS_315_VGA) &&
          (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x50) == 0x10) ) ) {
       isslavemode = TRUE;
    }
@@ -3427,59 +3262,59 @@ SiS_SetPitch(SiS_Private *SiS_Pr, ScrnInfoPtr pScrn)
 /*                 SiSSetMode()              */
 /*********************************************/
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 /* We need pScrn for setting the pitch correctly */
 BOOLEAN
-SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch)
+SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo, BOOLEAN dosetpitch)
 #else
 BOOLEAN
-SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
+SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 #endif
 {
-   USHORT  ModeIdIndex;
-   SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
-   unsigned char backupreg=0;
-#ifdef LINUX_KERNEL
-   USHORT  KeepLockReg;
-   ULONG   temp;
+   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+   unsigned short RealModeNo, ModeIdIndex;
+   unsigned char  backupreg = 0;
+#ifdef SIS_LINUX_KERNEL
+   unsigned short KeepLockReg;
 
    SiS_Pr->UseCustomMode = FALSE;
    SiS_Pr->CRT1UsesCustomMode = FALSE;
 #endif
 
+   SiS_Pr->SiS_flag_clearbuffer = 0;
+
    if(SiS_Pr->UseCustomMode) {
       ModeNo = 0xfe;
+   } else {
+#ifdef SIS_LINUX_KERNEL
+      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
+#endif
+      ModeNo &= 0x7f;
    }
 
-   SiSInitPtr(SiS_Pr, HwInfo);
+   /* Don't use FSTN mode for CRT1 */
+   RealModeNo = ModeNo;
+   if(ModeNo == 0x5b) ModeNo = 0x56;
+
+   SiSInitPtr(SiS_Pr);
    SiSRegInit(SiS_Pr, BaseAddr);
-   SiS_GetSysFlags(SiS_Pr, HwInfo);
+   SiS_GetSysFlags(SiS_Pr);
 
-#if defined(LINUX_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+   SiS_Pr->SiS_VGAINFO = 0x11;
+#if defined(SIS_XORG_XF86) && (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__))
    if(pScrn) SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
-   else
-#endif
-         SiS_Pr->SiS_VGAINFO = 0x11;
-
-   SiSInitPCIetc(SiS_Pr, HwInfo);
-   SiSSetLVDSetc(SiS_Pr, HwInfo);
-   SiSDetermineROMUsage(SiS_Pr, HwInfo);
-
-   SiS_Pr->SiS_flag_clearbuffer = 0;
-
-   if(!SiS_Pr->UseCustomMode) {
-#ifdef LINUX_KERNEL
-      if(!(ModeNo & 0x80)) SiS_Pr->SiS_flag_clearbuffer = 1;
 #endif
-      ModeNo &= 0x7f;
-   }
 
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
    KeepLockReg = SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
 #endif
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
 
-   SiS_UnLockCRT2(SiS_Pr, HwInfo);
+   SiSInitPCIetc(SiS_Pr);
+   SiSSetLVDSetc(SiS_Pr);
+   SiSDetermineROMUsage(SiS_Pr);
+
+   SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
       if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3487,13 +3322,13 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
       ModeIdIndex = 0;
    }
 
-   SiS_GetVBType(SiS_Pr, HwInfo);
+   SiS_GetVBType(SiS_Pr);
 
    /* Init/restore some VB registers */
-
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(HwInfo->jChipType >= SIS_315H) {
-         SiS_ResetVB(SiS_Pr, HwInfo);
+   SiS_InitVB(SiS_Pr);
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
+         SiS_ResetVB(SiS_Pr);
         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
         SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -3503,21 +3338,20 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
    }
 
    /* Get VB information (connectors, connected devices) */
-   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, (SiS_Pr->UseCustomMode) ? 0 : 1);
-   SiS_SetYPbPr(SiS_Pr, HwInfo);
-   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-   SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
-
-#ifdef LINUX_KERNEL
-   /* 3. Check memory size (Kernel framebuffer driver only) */
-   temp = SiS_CheckMemorySize(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
-   if(!temp) return(0);
+   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, (SiS_Pr->UseCustomMode) ? 0 : 1);
+   SiS_SetYPbPr(SiS_Pr);
+   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+#ifdef SIS_LINUX_KERNEL
+   /* Check memory size (kernel framebuffer driver only) */
+   if(!SiS_CheckMemorySize(SiS_Pr, ModeNo, ModeIdIndex)) {
+      return FALSE;
+   }
 #endif
 
-   if(HwInfo->jChipType >= SIS_315H) {
-      SiS_SetupCR5x(SiS_Pr, HwInfo);
-   }
+   SiS_OpenCRTC(SiS_Pr);
 
    if(SiS_Pr->UseCustomMode) {
       SiS_Pr->CRT1UsesCustomMode = TRUE;
@@ -3530,38 +3364,41 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
    /* Set mode on CRT1 */
    if( (SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) ||
        (!(SiS_Pr->SiS_VBInfo & SwitchCRT2)) ) {
-      SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+      SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
    }
 
    /* Set mode on CRT2 */
    if(SiS_Pr->SiS_VBInfo & (SetSimuScanMode | SwitchCRT2 | SetCRT2ToLCDA)) {
       if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
-          (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
-          (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
-          (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
-         SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+         (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
+         (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
+         (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
+        SiS_SetCRT2Group(SiS_Pr, RealModeNo);
       }
    }
 
    SiS_HandleCRT1(SiS_Pr);
 
-   SiS_StrangeStuff(SiS_Pr, HwInfo);
+   SiS_StrangeStuff(SiS_Pr);
 
    SiS_DisplayOn(SiS_Pr);
    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
 
-   if(HwInfo->jChipType >= SIS_315H) {
+#ifdef SIS315H
+   if(SiS_Pr->ChipType >= SIS_315H) {
       if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-         if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
+        if(!(SiS_IsDualEdge(SiS_Pr))) {
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
         }
       }
    }
+#endif
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(HwInfo->jChipType >= SIS_315H) {
-         if(!SiS_Pr->SiS_ROMNew) {
-           if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
+#ifdef SIS315H
+        if(!SiS_Pr->SiS_ROMNew) {
+           if(SiS_IsVAMode(SiS_Pr)) {
               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
            } else {
               SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
@@ -3574,23 +3411,24 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
            if((ModeNo == 0x03) || (ModeNo == 0x10)) {
               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x51,0x80);
               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x56,0x08);
-            }
+           }
         }
 
         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
         }
-      } else if((HwInfo->jChipType == SIS_630) ||
-                (HwInfo->jChipType == SIS_730)) {
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
+#endif
+      } else if((SiS_Pr->ChipType == SIS_630) ||
+               (SiS_Pr->ChipType == SIS_730)) {
+        SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
       }
    }
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
    if(pScrn) {
       /* SetPitch: Adapt to virtual size & position */
       if((ModeNo > 0x13) && (dosetpitch)) {
-         SiS_SetPitch(SiS_Pr, pScrn);
+        SiS_SetPitch(SiS_Pr, pScrn);
       }
 
       /* Backup/Set ModeNo in BIOS scratch area */
@@ -3598,33 +3436,37 @@ SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo)
    }
 #endif
 
-#ifdef LINUX_KERNEL  /* We never lock registers in XF86 */
-   if(KeepLockReg == 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-   else SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
+   SiS_CloseCRTC(SiS_Pr);
+
+   SiS_Handle760(SiS_Pr);
+
+#ifdef SIS_LINUX_KERNEL
+   /* We never lock registers in XF86 */
+   if(KeepLockReg != 0xA1) SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x00);
 #endif
 
    return TRUE;
 }
 
 /*********************************************/
-/*          XFree86: SiSBIOSSetMode()        */
+/*       X.org/XFree86: SiSBIOSSetMode()     */
 /*           for non-Dual-Head mode          */
 /*********************************************/
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 BOOLEAN
-SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
                DisplayModePtr mode, BOOLEAN IsCustom)
 {
    SISPtr pSiS = SISPTR(pScrn);
-   UShort ModeNo = 0;
+   unsigned short ModeNo = 0;
 
    SiS_Pr->UseCustomMode = FALSE;
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting custom mode %dx%d\n",
-               SiS_Pr->CHDisplay,
+               SiS_Pr->CHDisplay,
                (mode->Flags & V_INTERLACE ? SiS_Pr->CVDisplay * 2 :
                   (mode->Flags & V_DBLSCAN ? SiS_Pr->CVDisplay / 2 :
                      SiS_Pr->CVDisplay)));
@@ -3632,32 +3474,33 @@ SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
    } else {
 
       /* Don't need vbflags here; checks done earlier */
-      ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
+      ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
       if(!ModeNo) return FALSE;
 
       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, "Setting standard mode 0x%x\n", ModeNo);
 
    }
 
-   return(SiSSetMode(SiS_Pr, HwInfo, pScrn, ModeNo, TRUE));
+   return(SiSSetMode(SiS_Pr, pScrn, ModeNo, TRUE));
 }
 
 /*********************************************/
-/*       XFree86: SiSBIOSSetModeCRT2()       */
+/*    X.org/XFree86: SiSBIOSSetModeCRT2()    */
 /*           for Dual-Head modes             */
 /*********************************************/
+
 BOOLEAN
-SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
                DisplayModePtr mode, BOOLEAN IsCustom)
 {
-   USHORT  ModeIdIndex;
-   SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
-   UShort  ModeNo   = 0;
-   unsigned char backupreg=0;
-   SISPtr  pSiS     = SISPTR(pScrn);
+   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
+   SISPtr  pSiS = SISPTR(pScrn);
 #ifdef SISDUALHEAD
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
 #endif
+   unsigned short ModeIdIndex;
+   unsigned short ModeNo = 0;
+   unsigned char  backupreg = 0;
 
    SiS_Pr->UseCustomMode = FALSE;
 
@@ -3672,22 +3515,25 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
 
    } else {
 
-         ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
-         if(!ModeNo) return FALSE;
+        ModeNo = SiS_GetModeNumber(pScrn, mode, pSiS->VBFlags);
+        if(!ModeNo) return FALSE;
 
    }
 
    SiSRegInit(SiS_Pr, BaseAddr);
-   SiSInitPtr(SiS_Pr, HwInfo);
-   SiS_GetSysFlags(SiS_Pr, HwInfo);
-#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+   SiSInitPtr(SiS_Pr);
+   SiS_GetSysFlags(SiS_Pr);
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
 #else
    SiS_Pr->SiS_VGAINFO = 0x11;
 #endif
-   SiSInitPCIetc(SiS_Pr, HwInfo);
-   SiSSetLVDSetc(SiS_Pr, HwInfo);
-   SiSDetermineROMUsage(SiS_Pr, HwInfo);
+
+   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
+
+   SiSInitPCIetc(SiS_Pr);
+   SiSSetLVDSetc(SiS_Pr);
+   SiSDetermineROMUsage(SiS_Pr);
 
    /* Save mode info so we can set it from within SetMode for CRT1 */
 #ifdef SISDUALHEAD
@@ -3700,23 +3546,20 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
       pSiSEnt->CRT2CR35 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
       pSiSEnt->CRT2CR38 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
 #if 0
-      /* We can't set CRT2 mode before CRT1 mode is set */
+      /* We can't set CRT2 mode before CRT1 mode is set - says who...? */
       if(pSiSEnt->CRT1ModeNo == -1) {
-        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
                "Setting CRT2 mode delayed until after setting CRT1 mode\n");
-        return TRUE;
+        return TRUE;
       }
 #endif
       pSiSEnt->CRT2ModeSet = TRUE;
    }
 #endif
 
-   /* We don't clear the buffer in X */
-   SiS_Pr->SiS_flag_clearbuffer=0;
-
    if(SiS_Pr->UseCustomMode) {
 
-      USHORT temptemp = SiS_Pr->CVDisplay;
+      unsigned short temptemp = SiS_Pr->CVDisplay;
 
       if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
       else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
@@ -3728,13 +3571,11 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
    } else {
 
       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
-         "Setting standard mode 0x%x on CRT2\n", ModeNo);
+         "Setting standard mode 0x%x on CRT2\n", ModeNo);
 
    }
 
-   SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
-
-   SiS_UnLockCRT2(SiS_Pr, HwInfo);
+   SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
       if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3742,56 +3583,59 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
       ModeIdIndex = 0;
    }
 
-   SiS_GetVBType(SiS_Pr, HwInfo);
+   SiS_GetVBType(SiS_Pr);
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(HwInfo->jChipType >= SIS_315H) {
-        SiS_ResetVB(SiS_Pr, HwInfo);
+   SiS_InitVB(SiS_Pr);
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
+        SiS_ResetVB(SiS_Pr);
         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x32,0x10);
         SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x00,0x0c);
-         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+        backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
-         backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+        backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
       }
    }
 
    /* Get VB information (connectors, connected devices) */
    if(!SiS_Pr->UseCustomMode) {
-      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 1);
+      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 1);
    } else {
       /* If this is a custom mode, we don't check the modeflag for CRT2Mode */
-      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0);
+      SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
    }
-   SiS_SetYPbPr(SiS_Pr, HwInfo);
-   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-   SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
+   SiS_SetYPbPr(SiS_Pr);
+   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_SetLowModeTest(SiS_Pr, ModeNo);
+
+   SiS_ResetSegmentRegisters(SiS_Pr);
 
    /* Set mode on CRT2 */
    if( (SiS_Pr->SiS_VBType & VB_SISVB)    ||
        (SiS_Pr->SiS_IF_DEF_LVDS     == 1) ||
        (SiS_Pr->SiS_IF_DEF_CH70xx   != 0) ||
        (SiS_Pr->SiS_IF_DEF_TRUMPION != 0) ) {
-      SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+      SiS_SetCRT2Group(SiS_Pr, ModeNo);
    }
 
-   SiS_StrangeStuff(SiS_Pr, HwInfo);
+   SiS_StrangeStuff(SiS_Pr);
 
    SiS_DisplayOn(SiS_Pr);
    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
 
-   if(HwInfo->jChipType >= SIS_315H) {
+   if(SiS_Pr->ChipType >= SIS_315H) {
       if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-         if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
+        if(!(SiS_IsDualEdge(SiS_Pr))) {
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
         }
       }
    }
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(HwInfo->jChipType >= SIS_315H) {
-         if(!SiS_Pr->SiS_ROMNew) {
-           if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
+        if(!SiS_Pr->SiS_ROMNew) {
+           if(SiS_IsVAMode(SiS_Pr)) {
               SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
            } else {
               SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x35,0xFE);
@@ -3803,8 +3647,8 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
         if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & SetCRT2ToLCD) {
            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
         }
-      } else if((HwInfo->jChipType == SIS_630) ||
-                (HwInfo->jChipType == SIS_730)) {
+      } else if((SiS_Pr->ChipType == SIS_630) ||
+               (SiS_Pr->ChipType == SIS_730)) {
          SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
       }
    }
@@ -3812,25 +3656,27 @@ SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
    /* SetPitch: Adapt to virtual size & position */
    SiS_SetPitchCRT2(SiS_Pr, pScrn);
 
+   SiS_Handle760(SiS_Pr);
+
    return TRUE;
 }
 
 /*********************************************/
-/*       XFree86: SiSBIOSSetModeCRT1()       */
+/*    X.org/XFree86: SiSBIOSSetModeCRT1()    */
 /*           for Dual-Head modes             */
 /*********************************************/
 
 BOOLEAN
-SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
+SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
                    DisplayModePtr mode, BOOLEAN IsCustom)
 {
+   SISIOADDRESS BaseAddr = SiS_Pr->IOAddress;
    SISPtr  pSiS = SISPTR(pScrn);
-   SISIOADDRESS BaseAddr = HwInfo->ulIOAddress;
-   USHORT  ModeIdIndex, ModeNo=0;
-   UCHAR backupreg=0;
+   unsigned short ModeIdIndex, ModeNo = 0;
+   unsigned char  backupreg = 0;
 #ifdef SISDUALHEAD
    SISEntPtr pSiSEnt = pSiS->entityPrivate;
-   UCHAR backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
+   unsigned char  backupcr30, backupcr31, backupcr38, backupcr35, backupp40d=0;
    BOOLEAN backupcustom;
 #endif
 
@@ -3838,43 +3684,41 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
 
    if((IsCustom) && (SiS_CheckBuildCustomMode(pScrn, mode, pSiS->VBFlags))) {
 
-         USHORT temptemp = SiS_Pr->CVDisplay;
+        unsigned short temptemp = SiS_Pr->CVDisplay;
 
-         if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
-         else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
+        if(SiS_Pr->CModeFlag & DoubleScanMode)     temptemp >>= 1;
+        else if(SiS_Pr->CInfoFlag & InterlaceMode) temptemp <<= 1;
 
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
                "Setting custom mode %dx%d on CRT1\n",
                SiS_Pr->CHDisplay, temptemp);
         ModeNo = 0xfe;
 
    } else {
 
-         ModeNo = SiS_GetModeNumber(pScrn, mode, 0);
-         if(!ModeNo) return FALSE;
+        ModeNo = SiS_GetModeNumber(pScrn, mode, 0); /* don't give VBFlags */
+        if(!ModeNo) return FALSE;
 
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
                "Setting standard mode 0x%x on CRT1\n", ModeNo);
    }
 
-   SiSInitPtr(SiS_Pr, HwInfo);
+   SiSInitPtr(SiS_Pr);
    SiSRegInit(SiS_Pr, BaseAddr);
-   SiS_GetSysFlags(SiS_Pr, HwInfo);
-#if (defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__))
+   SiS_GetSysFlags(SiS_Pr);
+#if defined(i386) || defined(__i386) || defined(__i386__) || defined(__AMD64__) || defined(__amd64__) || defined(__x86_64__)
    SiS_Pr->SiS_VGAINFO = SiS_GetSetBIOSScratch(pScrn, 0x489, 0xff);
 #else
    SiS_Pr->SiS_VGAINFO = 0x11;
 #endif
-   SiSInitPCIetc(SiS_Pr, HwInfo);
-   SiSSetLVDSetc(SiS_Pr, HwInfo);
-   SiSDetermineROMUsage(SiS_Pr, HwInfo);
-
-   /* We don't clear the buffer in X */
-   SiS_Pr->SiS_flag_clearbuffer = 0;
 
    SiS_SetReg(SiS_Pr->SiS_P3c4,0x05,0x86);
 
-   SiS_UnLockCRT2(SiS_Pr, HwInfo);
+   SiSInitPCIetc(SiS_Pr);
+   SiSSetLVDSetc(SiS_Pr);
+   SiSDetermineROMUsage(SiS_Pr);
+
+   SiS_UnLockCRT2(SiS_Pr);
 
    if(!SiS_Pr->UseCustomMode) {
       if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
@@ -3883,10 +3727,11 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
    }
 
    /* Determine VBType */
-   SiS_GetVBType(SiS_Pr, HwInfo);
+   SiS_GetVBType(SiS_Pr);
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(HwInfo->jChipType >= SIS_315H) {
+   SiS_InitVB(SiS_Pr);
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
       } else {
          backupreg = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
@@ -3895,25 +3740,29 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
 
    /* Get VB information (connectors, connected devices) */
    /* (We don't care if the current mode is a CRT2 mode) */
-   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, 0);
-   SiS_SetYPbPr(SiS_Pr, HwInfo);
-   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-   SiS_SetLowModeTest(SiS_Pr, ModeNo, HwInfo);
+   SiS_GetVBInfo(SiS_Pr, ModeNo, ModeIdIndex, 0);
+   SiS_SetYPbPr(SiS_Pr);
+   SiS_SetTVMode(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_GetLCDResInfo(SiS_Pr, ModeNo, ModeIdIndex);
+   SiS_SetLowModeTest(SiS_Pr, ModeNo);
 
-   if(HwInfo->jChipType >= SIS_315H) {
-      SiS_SetupCR5x(SiS_Pr, HwInfo);
-   }
+   SiS_OpenCRTC(SiS_Pr);
 
    /* Set mode on CRT1 */
-   SiS_SetCRT1Group(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+   SiS_SetCRT1Group(SiS_Pr, ModeNo, ModeIdIndex);
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-      SiS_SetCRT2Group(SiS_Pr, HwInfo, ModeNo);
+      SiS_SetCRT2Group(SiS_Pr, ModeNo);
    }
 
    /* SetPitch: Adapt to virtual size & position */
    SiS_SetPitchCRT1(SiS_Pr, pScrn);
 
+   SiS_HandleCRT1(SiS_Pr);
+
+   SiS_StrangeStuff(SiS_Pr);
+
+   SiS_CloseCRTC(SiS_Pr);
+
 #ifdef SISDUALHEAD
    if(pSiS->DualHeadMode) {
       pSiSEnt->CRT1ModeNo = ModeNo;
@@ -3933,7 +3782,7 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
 #ifdef SISDUALHEAD
    if(pSiS->DualHeadMode) {
       if(pSiSEnt->CRT2ModeNo != -1) {
-         xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
+        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
                                "(Re-)Setting mode for CRT2\n");
         backupcustom = SiS_Pr->UseCustomMode;
         backupcr30 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
@@ -3952,9 +3801,11 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
            SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,pSiSEnt->CRT2CR35);
            SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,pSiSEnt->CRT2CR38);
         }
-        SiSBIOSSetModeCRT2(SiS_Pr, HwInfo, pSiSEnt->pScrn_1,
+
+        SiSBIOSSetModeCRT2(SiS_Pr, pSiSEnt->pScrn_1,
                            pSiSEnt->CRT2DMode, pSiSEnt->CRT2IsCustom);
-         SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
+
+        SiS_SetReg(SiS_Pr->SiS_P3d4,0x30,backupcr30);
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x31,backupcr31);
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupcr35);
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupcr38);
@@ -3970,22 +3821,20 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
     * possibly overwritten
     */
 
-   SiS_HandleCRT1(SiS_Pr);
-
-   SiS_StrangeStuff(SiS_Pr, HwInfo);
-
    SiS_DisplayOn(SiS_Pr);
    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xFF);
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-      if(HwInfo->jChipType >= SIS_315H) {
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+      if(SiS_Pr->ChipType >= SIS_315H) {
         SiS_SetReg(SiS_Pr->SiS_P3d4,0x38,backupreg);
-      } else if((HwInfo->jChipType == SIS_630) ||
-                (HwInfo->jChipType == SIS_730)) {
+      } else if((SiS_Pr->ChipType == SIS_630) ||
+                (SiS_Pr->ChipType == SIS_730)) {
          SiS_SetReg(SiS_Pr->SiS_P3d4,0x35,backupreg);
       }
    }
 
+   SiS_Handle760(SiS_Pr);
+
    /* Backup/Set ModeNo in BIOS scratch area */
    SiS_GetSetModeID(pScrn,ModeNo);
 
@@ -3993,84 +3842,6 @@ SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
 }
 #endif /* Linux_XF86 */
 
-
-#ifdef LINUX_XF86
-BOOLEAN
-SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
-  const USHORT PanelTypeTable300[16] = {
-      0xc101, 0xc117, 0x0121, 0xc135, 0xc142, 0xc152, 0xc162, 0xc072,
-      0xc181, 0xc192, 0xc1a1, 0xc1b6, 0xc1c2, 0xc0d2, 0xc1e2, 0xc1f2
-  };
-  const USHORT PanelTypeTable31030x[16] = {
-      0xc102, 0xc112, 0x0122, 0xc132, 0xc142, 0xc152, 0xc169, 0xc179,
-      0x0189, 0xc192, 0xc1a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-  };
-  const USHORT PanelTypeTable310LVDS[16] = {
-      0xc111, 0xc122, 0xc133, 0xc144, 0xc155, 0xc166, 0xc177, 0xc188,
-      0xc199, 0xc0aa, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-  };
-  USHORT tempax,tempbx,temp;
-
-  if(HwInfo->jChipType < SIS_315H) {
-
-     tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
-     tempbx = tempax & 0x0F;
-     if(!(tempax & 0x10)){
-        if(SiS_Pr->SiS_IF_DEF_LVDS == 1){
-           tempbx = 0;
-           temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x38);
-           if(temp & 0x40) tempbx |= 0x08;
-           if(temp & 0x20) tempbx |= 0x02;
-           if(temp & 0x01) tempbx |= 0x01;
-           temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x39);
-           if(temp & 0x80) tempbx |= 0x04;
-        } else {
-           return 0;
-        }
-     }
-     tempbx = PanelTypeTable300[tempbx];
-     tempbx |= LCDSync;
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp);
-     temp = (tempbx & 0xFF00) >> 8;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp);
-
-  } else {
-
-     if(HwInfo->jChipType >= SIS_661) return 0;
-
-     tempax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1a);
-     tempax &= 0x1e;
-     tempax >>= 1;
-     if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if(tempax == 0) {
-           /* TODO: Include HUGE detection routine
-                   (Probably not worth bothering)
-           */
-           return 0;
-        }
-        temp = tempax & 0xff;
-        tempax--;
-        tempbx = PanelTypeTable310LVDS[tempax];
-     } else {
-        tempbx = PanelTypeTable31030x[tempax];
-        temp = tempbx & 0xff;
-     }
-     SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,temp);
-     tempbx = (tempbx & 0xff00) >> 8;
-     temp = tempbx & 0xc1;
-     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,~(LCDSyncBit|LCDRGB18Bit),temp);
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        temp = tempbx & 0x04;
-        SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x39,0xfb,temp);
-     }
-
-  }
-  return 1;
-}
-#endif
-
 #ifndef GETBITSTR
 #define BITMASK(h,l)           (((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
 #define GENMASK(mask)          BITMASK(1?mask,0?mask)
@@ -4078,26 +3849,28 @@ SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 #define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
 #endif
 
-static void
-SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
+void
+SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth)
 {
+   int x = 1; /* Fix sync */
+
    SiS_Pr->CCRT1CRTC[0]  =  ((SiS_Pr->CHTotal >> 3) - 5) & 0xff;               /* CR0 */
    SiS_Pr->CCRT1CRTC[1]  =  (SiS_Pr->CHDisplay >> 3) - 1;                      /* CR1 */
    SiS_Pr->CCRT1CRTC[2]  =  (SiS_Pr->CHBlankStart >> 3) - 1;                   /* CR2 */
    SiS_Pr->CCRT1CRTC[3]  =  (((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x1F) | 0x80;   /* CR3 */
    SiS_Pr->CCRT1CRTC[4]  =  (SiS_Pr->CHSyncStart >> 3) + 3;                    /* CR4 */
    SiS_Pr->CCRT1CRTC[5]  =  ((((SiS_Pr->CHBlankEnd >> 3) - 1) & 0x20) << 2) |  /* CR5 */
-                                   (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
+                           (((SiS_Pr->CHSyncEnd >> 3) + 3) & 0x1F);
 
-   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal - 2) & 0xFF;                      /* CR6 */
-   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal - 2) & 0x100) >> 8)             /* CR7 */
-                         | (((SiS_Pr->CVDisplay - 1) & 0x100) >> 7)
-                         | ((SiS_Pr->CVSyncStart & 0x100) >> 6)
-                         | (((SiS_Pr->CVBlankStart - 1) & 0x100) >> 5)
+   SiS_Pr->CCRT1CRTC[6]  =  (SiS_Pr->CVTotal       - 2) & 0xFF;                        /* CR6 */
+   SiS_Pr->CCRT1CRTC[7]  =  (((SiS_Pr->CVTotal     - 2) & 0x100) >> 8)         /* CR7 */
+                         | (((SiS_Pr->CVDisplay   - 1) & 0x100) >> 7)
+                         | (((SiS_Pr->CVSyncStart - x) & 0x100) >> 6)
+                         | (((SiS_Pr->CVBlankStart- 1) & 0x100) >> 5)
                          | 0x10
-                         | (((SiS_Pr->CVTotal - 2) & 0x200)   >> 4)
-                         | (((SiS_Pr->CVDisplay - 1) & 0x200) >> 3)
-                         | ((SiS_Pr->CVSyncStart & 0x200) >> 2);
+                         | (((SiS_Pr->CVTotal     - 2) & 0x200) >> 4)
+                         | (((SiS_Pr->CVDisplay   - 1) & 0x200) >> 3)
+                         | (((SiS_Pr->CVSyncStart - x) & 0x200) >> 2);
 
    SiS_Pr->CCRT1CRTC[16] = ((((SiS_Pr->CVBlankStart - 1) & 0x200) >> 4) >> 5);         /* CR9 */
 
@@ -4106,55 +3879,44 @@ SiS_CalcCRRegisters(SiS_Private *SiS_Pr, int depth)
       else if(SiS_Pr->CHDisplay >= 640)  SiS_Pr->CCRT1CRTC[16] |= 0x40;
    }
 
-#if 0
-   if (mode->VScan >= 32)
-       regp->CRTC[9] |= 0x1F;
-   else if (mode->VScan > 1)
-       regp->CRTC[9] |= mode->VScan - 1;
-#endif
-
-   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart     ) & 0xFF;                  /* CR10 */
-   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd      ) & 0x0F) | 0x80;          /* CR11 */
+   SiS_Pr->CCRT1CRTC[8] =  (SiS_Pr->CVSyncStart  - x) & 0xFF;                  /* CR10 */
+   SiS_Pr->CCRT1CRTC[9] =  ((SiS_Pr->CVSyncEnd   - x) & 0x0F) | 0x80;          /* CR11 */
    SiS_Pr->CCRT1CRTC[10] = (SiS_Pr->CVDisplay    - 1) & 0xFF;                  /* CR12 */
    SiS_Pr->CCRT1CRTC[11] = (SiS_Pr->CVBlankStart - 1) & 0xFF;                  /* CR15 */
    SiS_Pr->CCRT1CRTC[12] = (SiS_Pr->CVBlankEnd   - 1) & 0xFF;                  /* CR16 */
 
    SiS_Pr->CCRT1CRTC[13] =                                                     /* SRA */
-                        GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
-                        GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
-                        GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
-                        GETBITSTR((SiS_Pr->CVSyncStart   ), 10:10, 3:3) |
-                        GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
-                        GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
+                       GETBITSTR((SiS_Pr->CVTotal     -2), 10:10, 0:0) |
+                       GETBITSTR((SiS_Pr->CVDisplay   -1), 10:10, 1:1) |
+                       GETBITSTR((SiS_Pr->CVBlankStart-1), 10:10, 2:2) |
+                       GETBITSTR((SiS_Pr->CVSyncStart -x), 10:10, 3:3) |
+                       GETBITSTR((SiS_Pr->CVBlankEnd  -1),   8:8, 4:4) |
+                       GETBITSTR((SiS_Pr->CVSyncEnd     ),   4:4, 5:5) ;
 
    SiS_Pr->CCRT1CRTC[14] =                                                     /* SRB */
-                        GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
-                        GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
-                        GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
-                        GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
+                       GETBITSTR((SiS_Pr->CHTotal      >> 3) - 5, 9:8, 1:0) |
+                       GETBITSTR((SiS_Pr->CHDisplay    >> 3) - 1, 9:8, 3:2) |
+                       GETBITSTR((SiS_Pr->CHBlankStart >> 3) - 1, 9:8, 5:4) |
+                       GETBITSTR((SiS_Pr->CHSyncStart  >> 3) + 3, 9:8, 7:6) ;
 
 
    SiS_Pr->CCRT1CRTC[15] =                                                     /* SRC */
-                        GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
-                        GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
+                       GETBITSTR((SiS_Pr->CHBlankEnd >> 3) - 1, 7:6, 1:0) |
+                       GETBITSTR((SiS_Pr->CHSyncEnd  >> 3) + 3, 5:5, 2:2) ;
 }
 
 void
-SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex)
 {
-   USHORT modeflag, tempax, tempbx, VGAHDE = SiS_Pr->SiS_VGAHDE;
-   int i,j;
+   unsigned short modeflag, tempax, tempbx = 0, remaining = 0;
+   unsigned short VGAHDE = SiS_Pr->SiS_VGAHDE;
+   int i, j;
 
    /* 1:1 data: use data set by setcrt1crtc() */
    if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
 
-   if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-   } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-   } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-   }
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
 
    if(modeflag & HalfDCLK) VGAHDE >>= 1;
 
@@ -4164,32 +3926,91 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
    SiS_Pr->CVDisplay = SiS_Pr->SiS_VGAVDE;
    SiS_Pr->CVBlankStart = SiS_Pr->SiS_VGAVDE;
 
-   tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
-   tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
-   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-      tempax = SiS_Pr->PanelXRes;
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+      tempbx = SiS_Pr->SiS_VGAHT;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         tempbx = SiS_Pr->PanelHT;
+      }
+      if(modeflag & HalfDCLK) tempbx >>= 1;
+      remaining = tempbx % 8;
+#endif
+   } else {
+#ifdef SIS315H
+      /* OK for LCDA, LVDS */
+      tempbx = SiS_Pr->PanelHT - SiS_Pr->PanelXRes;
+      tempax = SiS_Pr->SiS_VGAHDE;  /* not /2 ! */
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+         tempax = SiS_Pr->PanelXRes;
+      }
+      tempbx += tempax;
+      if(modeflag & HalfDCLK) tempbx -= VGAHDE;
+#endif
    }
-   tempbx += tempax;
-   if(modeflag & HalfDCLK) tempbx -= VGAHDE;
    SiS_Pr->CHTotal = SiS_Pr->CHBlankEnd = tempbx;
 
-   tempax = VGAHDE;
-   tempbx = SiS_Pr->CHTotal;
-   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-      tempbx = SiS_Pr->PanelXRes;
-      if(modeflag & HalfDCLK) tempbx >>= 1;
-      tempax += ((tempbx - tempax) >> 1);
+   if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+      if(SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) {
+        SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE + ((SiS_Pr->PanelHRS + 1) & ~1);
+        SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + SiS_Pr->PanelHRE;
+        if(modeflag & HalfDCLK) {
+           SiS_Pr->CHSyncStart >>= 1;
+           SiS_Pr->CHSyncEnd >>= 1;
+        }
+      } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        tempax = (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) >> 1;
+        tempbx = (SiS_Pr->PanelHRS + 1) & ~1;
+        if(modeflag & HalfDCLK) {
+           tempax >>= 1;
+           tempbx >>= 1;
+        }
+        SiS_Pr->CHSyncStart = (VGAHDE + tempax + tempbx + 7) & ~7;
+        tempax = SiS_Pr->PanelHRE + 7;
+        if(modeflag & HalfDCLK) tempax >>= 1;
+        SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + tempax) & ~7;
+      } else {
+        SiS_Pr->CHSyncStart = SiS_Pr->SiS_VGAHDE;
+        if(modeflag & HalfDCLK) {
+           SiS_Pr->CHSyncStart >>= 1;
+           tempax = ((SiS_Pr->CHTotal - SiS_Pr->CHSyncStart) / 3) << 1;
+           SiS_Pr->CHSyncEnd = SiS_Pr->CHSyncStart + tempax;
+        } else {
+           SiS_Pr->CHSyncEnd = (SiS_Pr->CHSyncStart + (SiS_Pr->CHTotal / 10) + 7) & ~7;
+           SiS_Pr->CHSyncStart += 8;
+        }
+      }
+#endif
+   } else {
+#ifdef SIS315H
+      tempax = VGAHDE;
+      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+        tempbx = SiS_Pr->PanelXRes;
+        if(modeflag & HalfDCLK) tempbx >>= 1;
+        tempax += ((tempbx - tempax) >> 1);
+      }
+      tempax += SiS_Pr->PanelHRS;
+      SiS_Pr->CHSyncStart = tempax;
+      tempax += SiS_Pr->PanelHRE;
+      SiS_Pr->CHSyncEnd = tempax;
+#endif
    }
 
-   tempax += SiS_Pr->PanelHRS;
-   SiS_Pr->CHSyncStart = tempax;
-   tempax += SiS_Pr->PanelHRE;
-   SiS_Pr->CHSyncEnd = tempax;
-
    tempbx = SiS_Pr->PanelVT - SiS_Pr->PanelYRes;
    tempax = SiS_Pr->SiS_VGAVDE;
    if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
       tempax = SiS_Pr->PanelYRes;
+   } else if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+      /* Stupid hack for 640x400/320x200 */
+      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+        if((tempax + tempbx) == 438) tempbx += 16;
+      } else if((SiS_Pr->SiS_LCDResInfo == Panel_800x600) ||
+               (SiS_Pr->SiS_LCDResInfo == Panel_1024x600)) {
+        tempax = 0;
+        tempbx = SiS_Pr->SiS_VGAVT;
+      }
+#endif
    }
    SiS_Pr->CVTotal = SiS_Pr->CVBlankEnd = tempbx + tempax;
 
@@ -4201,22 +4022,28 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
    SiS_Pr->CVSyncStart = tempax;
    tempax += SiS_Pr->PanelVRE;
    SiS_Pr->CVSyncEnd = tempax;
+   if(SiS_Pr->ChipType < SIS_315H) {
+      SiS_Pr->CVSyncStart--;
+      SiS_Pr->CVSyncEnd--;
+   }
 
    SiS_CalcCRRegisters(SiS_Pr, 8);
+   SiS_Pr->CCRT1CRTC[15] &= ~0xF8;
+   SiS_Pr->CCRT1CRTC[15] |= (remaining << 4);
    SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
 
    SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
 
-   for(i=0,j=0;i<=7;i++,j++) {
+   for(i = 0, j = 0; i <= 7; i++, j++) {
       SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
    }
-   for(j=0x10;i<=10;i++,j++) {
+   for(j = 0x10; i <= 10; i++, j++) {
       SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
    }
-   for(j=0x15;i<=12;i++,j++) {
+   for(j = 0x15; i <= 12; i++, j++) {
       SiS_SetReg(SiS_Pr->SiS_P3d4,j,SiS_Pr->CCRT1CRTC[i]);
    }
-   for(j=0x0A;i<=15;i++,j++) {
+   for(j = 0x0A; i <= 15; i++, j++) {
       SiS_SetReg(SiS_Pr->SiS_P3c4,j,SiS_Pr->CCRT1CRTC[i]);
    }
 
@@ -4227,1092 +4054,192 @@ SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
    if(modeflag & DoubleScanMode) tempax |= 0x80;
    SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,0x5F,tempax);
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
    xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
-               SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+       SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
        SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
        SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
-
    xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+       SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
        SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
        SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
        SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
    xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+       SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
        SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
        SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
        SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
    xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
 #endif
+#endif
 }
 
-#ifdef LINUX_XF86
-
 void
-SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c)
-{
-   int          out_n, out_dn, out_div, out_sbit, out_scale;
-   unsigned int vclk[5];
-
-#define Midx         0
-#define Nidx         1
-#define VLDidx       2
-#define Pidx         3
-#define PSNidx       4
-
-   if(SiS_compute_vclk(clock, &out_n, &out_dn, &out_div, &out_sbit, &out_scale)) {
-      (*p2b) = (out_div == 2) ? 0x80 : 0x00;
-      (*p2b) |= ((out_n - 1) & 0x7f);
-      (*p2c) = (out_dn - 1) & 0x1f;
-      (*p2c) |= (((out_scale - 1) & 3) << 5);
-      (*p2c) |= ((out_sbit & 0x01) << 7);
-#ifdef TWDEBUG
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sb %d sc %d\n",
-                clock, out_n, out_dn, out_div, out_sbit, out_scale);
+SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+                       int xres, int yres,
+#ifdef SIS_XORG_XF86
+                       DisplayModePtr current
 #endif
-   } else {
-      SiSCalcClock(pScrn, clock, 2, vclk);
-      (*p2b) = (vclk[VLDidx] == 2) ? 0x80 : 0x00;
-      (*p2b) |= (vclk[Midx] - 1) & 0x7f;
-      (*p2c) = (vclk[Nidx] - 1) & 0x1f;
-      if(vclk[Pidx] <= 4) {
-         /* postscale 1,2,3,4 */
-         (*p2c) |= ((vclk[Pidx] - 1) & 3) << 5;
-      } else {
-         /* postscale 6,8 */
-         (*p2c) |= (((vclk[Pidx] / 2) - 1) & 3) << 5;
-        (*p2c) |= 0x80;
-      }
-#ifdef TWDEBUG
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock %d: n %d dn %d div %d sc %d\n",
-                clock, vclk[Midx], vclk[Nidx], vclk[VLDidx], vclk[Pidx]);
-#endif
-   }
-}
-
+#ifdef SIS_LINUX_KERNEL
+                       struct fb_var_screeninfo *var, BOOLEAN writeres
 #endif
-
-/* ================ XFREE86/X.ORG ================= */
-
-/* Helper functions */
-
-#ifdef LINUX_XF86
-
-USHORT
-SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags)
+)
 {
-   SISPtr pSiS = SISPTR(pScrn);
-   int    depth = pSiS->CurrentLayout.bitsPerPixel;
-
-   pSiS->SiS_Pr->CModeFlag = 0;
-   
-   pSiS->SiS_Pr->CDClock = mode->Clock;
-
-   pSiS->SiS_Pr->CHDisplay = mode->HDisplay;
-   pSiS->SiS_Pr->CHSyncStart = mode->HSyncStart;
-   pSiS->SiS_Pr->CHSyncEnd = mode->HSyncEnd;
-   pSiS->SiS_Pr->CHTotal = mode->HTotal;
-
-   pSiS->SiS_Pr->CVDisplay = mode->VDisplay;
-   pSiS->SiS_Pr->CVSyncStart = mode->VSyncStart;
-   pSiS->SiS_Pr->CVSyncEnd = mode->VSyncEnd;
-   pSiS->SiS_Pr->CVTotal = mode->VTotal;
-
-   pSiS->SiS_Pr->CFlags = mode->Flags;
-
-   if(pSiS->SiS_Pr->CFlags & V_INTERLACE) {
-      pSiS->SiS_Pr->CVDisplay >>= 1;
-      pSiS->SiS_Pr->CVSyncStart >>= 1;
-      pSiS->SiS_Pr->CVSyncEnd >>= 1;
-      pSiS->SiS_Pr->CVTotal >>= 1;
-   }
-   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN) {
-      /* pSiS->SiS_Pr->CDClock <<= 1; */
-      pSiS->SiS_Pr->CVDisplay <<= 1;
-      pSiS->SiS_Pr->CVSyncStart <<= 1;
-      pSiS->SiS_Pr->CVSyncEnd <<= 1;
-      pSiS->SiS_Pr->CVTotal <<= 1;
-   }
+   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
+   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
+   unsigned char  sr_data, cr_data, cr_data2;
+   int            A, B, C, D, E, F, temp;
 
-   pSiS->SiS_Pr->CHBlankStart = pSiS->SiS_Pr->CHDisplay;
-   pSiS->SiS_Pr->CHBlankEnd = pSiS->SiS_Pr->CHTotal;
-   pSiS->SiS_Pr->CVBlankStart = pSiS->SiS_Pr->CVSyncStart - 1;
-   pSiS->SiS_Pr->CVBlankEnd = pSiS->SiS_Pr->CVTotal;
+   sr_data = crdata[14];
 
-   SiS_MakeClockRegs(pScrn, pSiS->SiS_Pr->CDClock, &pSiS->SiS_Pr->CSR2B, &pSiS->SiS_Pr->CSR2C);
+   /* Horizontal total */
+   HT =  crdata[0] | ((unsigned short)(sr_data & 0x03) << 8);
+   A = HT + 5;
 
-   pSiS->SiS_Pr->CSRClock = (pSiS->SiS_Pr->CDClock / 1000) + 1;
+   /* Horizontal display enable end */
+   HDE = crdata[1] | ((unsigned short)(sr_data & 0x0C) << 6);
+   E = HDE + 1;
 
-   SiS_CalcCRRegisters(pSiS->SiS_Pr, depth);
+   /* Horizontal retrace (=sync) start */
+   HRS = crdata[4] | ((unsigned short)(sr_data & 0xC0) << 2);
+   F = HRS - E - 3;
 
-   switch(depth) {
-   case 8:  pSiS->SiS_Pr->CModeFlag |= 0x223b; break;
-   case 16: pSiS->SiS_Pr->CModeFlag |= 0x227d; break;
-   case 32: pSiS->SiS_Pr->CModeFlag |= 0x22ff; break;
-   default: return 0;
-   }
+   /* Horizontal blank start */
+   HBS = crdata[2] | ((unsigned short)(sr_data & 0x30) << 4);
 
-   if(pSiS->SiS_Pr->CFlags & V_DBLSCAN)
-      pSiS->SiS_Pr->CModeFlag |= DoubleScanMode;
+   sr_data = crdata[15];
+   cr_data = crdata[5];
 
-   if((pSiS->SiS_Pr->CVDisplay >= 1024)        ||
-      (pSiS->SiS_Pr->CVTotal >= 1024)   ||
-      (pSiS->SiS_Pr->CHDisplay >= 1024))
-      pSiS->SiS_Pr->CModeFlag |= LineCompareOff;
+   /* Horizontal blank end */
+   HBE = (crdata[3] & 0x1f) |
+         ((unsigned short)(cr_data & 0x80) >> 2) |
+         ((unsigned short)(sr_data & 0x03) << 6);
 
-   if(pSiS->SiS_Pr->CFlags & V_CLKDIV2)
-      pSiS->SiS_Pr->CModeFlag |= HalfDCLK;
+   /* Horizontal retrace (=sync) end */
+   HRE = (cr_data & 0x1f) | ((sr_data & 0x04) << 3);
 
-   pSiS->SiS_Pr->CInfoFlag = 0x0007;
+   temp = HBE - ((E - 1) & 255);
+   B = (temp > 0) ? temp : (temp + 256);
 
-   if(pSiS->SiS_Pr->CFlags & V_NHSYNC)
-      pSiS->SiS_Pr->CInfoFlag |= 0x4000;
+   temp = HRE - ((E + F + 3) & 63);
+   C = (temp > 0) ? temp : (temp + 64);
 
-   if(pSiS->SiS_Pr->CFlags & V_NVSYNC)
-      pSiS->SiS_Pr->CInfoFlag |= 0x8000;
+   D = B - F - C;
 
-   if(pSiS->SiS_Pr->CFlags & V_INTERLACE)
-      pSiS->SiS_Pr->CInfoFlag |= InterlaceMode;
-
-   pSiS->SiS_Pr->UseCustomMode = TRUE;
+#ifdef SIS_XORG_XF86
+   current->HDisplay   = (E * 8);
+   current->HSyncStart = (E * 8) + (F * 8);
+   current->HSyncEnd   = (E * 8) + (F * 8) + (C * 8);
+   current->HTotal     = (E * 8) + (F * 8) + (C * 8) + (D * 8);
 #ifdef TWDEBUG
-   xf86DrvMsg(0, X_INFO, "Custom mode %dx%d:\n",
-       pSiS->SiS_Pr->CHDisplay,pSiS->SiS_Pr->CVDisplay);
-   xf86DrvMsg(0, X_INFO, "Modeflag %04x, Infoflag %04x\n",
-       pSiS->SiS_Pr->CModeFlag, pSiS->SiS_Pr->CInfoFlag);
-   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       pSiS->SiS_Pr->CCRT1CRTC[0], pSiS->SiS_Pr->CCRT1CRTC[1],
-       pSiS->SiS_Pr->CCRT1CRTC[2], pSiS->SiS_Pr->CCRT1CRTC[3],
-       pSiS->SiS_Pr->CCRT1CRTC[4], pSiS->SiS_Pr->CCRT1CRTC[5],
-       pSiS->SiS_Pr->CCRT1CRTC[6], pSiS->SiS_Pr->CCRT1CRTC[7]);
-   xf86DrvMsg(0, X_INFO, "  0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
-       pSiS->SiS_Pr->CCRT1CRTC[8], pSiS->SiS_Pr->CCRT1CRTC[9],
-       pSiS->SiS_Pr->CCRT1CRTC[10], pSiS->SiS_Pr->CCRT1CRTC[11],
-       pSiS->SiS_Pr->CCRT1CRTC[12], pSiS->SiS_Pr->CCRT1CRTC[13],
-       pSiS->SiS_Pr->CCRT1CRTC[14], pSiS->SiS_Pr->CCRT1CRTC[15]);
-   xf86DrvMsg(0, X_INFO, "  0x%02x}},\n", pSiS->SiS_Pr->CCRT1CRTC[16]);
-   xf86DrvMsg(0, X_INFO, "Clock: 0x%02x, 0x%02x, %d\n",
-       pSiS->SiS_Pr->CSR2B, pSiS->SiS_Pr->CSR2C, pSiS->SiS_Pr->CSRClock);
-#endif
-   return 1;
-}
-
-int
-SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy)
-{
-   int i, j;
-   BOOLEAN done = FALSE;
-
-   i = 0;
-   while((!done) && (SiS_PlasmaTable[i].vendor) && panelvendor) {
-      if(SiS_PlasmaTable[i].vendor == panelvendor) {
-         for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
-           if(SiS_PlasmaTable[i].product[j] == panelproduct) {
-              if(SiS_PlasmaTable[i].maxx && SiS_PlasmaTable[i].maxy) {
-                 (*maxx) = (int)SiS_PlasmaTable[i].maxx;
-                 (*maxy) = (int)SiS_PlasmaTable[i].maxy;
-                 (*prefx) = (int)SiS_PlasmaTable[i].prefx;
-                 (*prefy) = (int)SiS_PlasmaTable[i].prefy;
-                 done = TRUE;
-                 xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-                       "Identified %s, correcting max X res %d, max Y res %d\n",
-                        SiS_PlasmaTable[i].plasmaname,
-                        SiS_PlasmaTable[i].maxx, SiS_PlasmaTable[i].maxy);
-                 break;
-              }
-           }
-        }
-      }
-      i++;
-   }
-   return (done) ? 1 : 0;
-}
-
-/* Build a list of supported modes:
- * Built-in modes for which we have all data are M_T_DEFAULT,
- * modes derived from DDC or database data are M_T_BUILTIN
- */
-DisplayModePtr
-SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi)
-{
-   SISPtr         pSiS = SISPTR(pScrn);
-   unsigned short VRE, VBE, VRS, VBS, VDE, VT;
-   unsigned short HRE, HBE, HRS, HBS, HDE, HT;
-   unsigned char  sr_data, cr_data, cr_data2, cr_data3;
-   unsigned char  sr2b, sr2c;
-   float          num, denum, postscalar, divider;
-   int            A, B, C, D, E, F, temp, i, j, k, l, index, vclkindex;
-   DisplayModePtr new = NULL, current = NULL, first = NULL;
-   BOOLEAN        done = FALSE;
-#if 0
-   DisplayModePtr backup = NULL;
-#endif
-
-   pSiS->backupmodelist = NULL;
-   pSiS->AddedPlasmaModes = FALSE;
-
-   /* Initialize our pointers */
-   if(pSiS->VGAEngine == SIS_300_VGA) {
-#ifdef SIS300
-      InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
+   xf86DrvMsg(0, X_INFO,
+               "H: A %d B %d C %d D %d E %d F %d  HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
+               A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
 #else
-      return NULL;
+   (void)VBS;  (void)HBS;  (void)A;
 #endif
-   } else if(pSiS->VGAEngine == SIS_315_VGA) {
-#ifdef SIS315H
-      InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
-      return NULL;
 #endif
-   } else return NULL;
-
-   i = 0;
-   while(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag != 0xFFFF) {
-
-      index = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRT1CRTC;
-
-      /* 0x5a (320x240) is a pure FTSN mode, not DSTN! */
-      if((!pSiS->FSTN) &&
-        (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID == 0x5a))  {
-           i++;
-          continue;
-      }
-      if((pSiS->FSTN) &&
-         (pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
-        (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240) &&
-        (pSiS->SiS_Pr->SiS_RefIndex[i].ModeID != 0x5a)) {
-          i++;
-          continue;
-      }
-
-      if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-      memset(new, 0, sizeof(DisplayModeRec));
-      if(!(new->name = xalloc(10))) {
-               xfree(new);
-               return first;
-      }
-      if(!first) first = new;
-      if(current) {
-         current->next = new;
-        new->prev = current;
-      }
-
-      current = new;
-
-      sprintf(current->name, "%dx%d", pSiS->SiS_Pr->SiS_RefIndex[i].XRes,
-                                      pSiS->SiS_Pr->SiS_RefIndex[i].YRes);
-
-      current->status = MODE_OK;
-
-      current->type = M_T_DEFAULT;
-
-      vclkindex = pSiS->SiS_Pr->SiS_RefIndex[i].Ext_CRTVCLK;
-      if(pSiS->VGAEngine == SIS_300_VGA) vclkindex &= 0x3F;
-
-      sr2b = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
-      sr2c = pSiS->SiS_Pr->SiS_VCLKData[vclkindex].SR2C;
-
-      divider = (sr2b & 0x80) ? 2.0 : 1.0;
-      postscalar = (sr2c & 0x80) ?
-              ( (((sr2c >> 5) & 0x03) == 0x02) ? 6.0 : 8.0) : (((sr2c >> 5) & 0x03) + 1.0);
-      num = (sr2b & 0x7f) + 1.0;
-      denum = (sr2c & 0x1f) + 1.0;
-
-#ifdef TWDEBUG
-      xf86DrvMsg(0, X_INFO, "------------\n");
-      xf86DrvMsg(0, X_INFO, "sr2b: %x sr2c %x div %f ps %f num %f denum %f\n",
-         sr2b, sr2c, divider, postscalar, num, denum);
+#ifdef SIS_LINUX_KERNEL
+   if(writeres) var->xres = xres = E * 8;
+   var->left_margin = D * 8;
+   var->right_margin = F * 8;
+   var->hsync_len = C * 8;
 #endif
 
-      current->Clock = (int)(14318 * (divider / postscalar) * (num / denum));
-
-      sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[14];
-       /* inSISIDXREG(SISSR, 0x0b, sr_data); */
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[0];
-       /* inSISIDXREG(SISCR, 0x00, cr_data); */
-
-      /* Horizontal total */
-      HT = (cr_data & 0xff) |
-           ((unsigned short) (sr_data & 0x03) << 8);
-      A = HT + 5;
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[1];
-       /* inSISIDXREG(SISCR, 0x01, cr_data); */
-
-      /* Horizontal display enable end */
-      HDE = (cr_data & 0xff) |
-            ((unsigned short) (sr_data & 0x0C) << 6);
-      E = HDE + 1;  /* 0x80 0x64 */
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[4];
-       /* inSISIDXREG(SISCR, 0x04, cr_data); */
-
-      /* Horizontal retrace (=sync) start */
-      HRS = (cr_data & 0xff) |
-            ((unsigned short) (sr_data & 0xC0) << 2);
-      F = HRS - E - 3;  /* 0x06 0x06 */
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[2];
-       /* inSISIDXREG(SISCR, 0x02, cr_data); */
-
-      /* Horizontal blank start */
-      HBS = (cr_data & 0xff) |
-            ((unsigned short) (sr_data & 0x30) << 4);
-
-      sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[15];
-       /* inSISIDXREG(SISSR, 0x0c, sr_data); */
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[3];
-       /* inSISIDXREG(SISCR, 0x03, cr_data);  */
-
-      cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[5];
-       /* inSISIDXREG(SISCR, 0x05, cr_data2); */
-
-      /* Horizontal blank end */
-      HBE = (cr_data & 0x1f) |
-            ((unsigned short) (cr_data2 & 0x80) >> 2) |
-           ((unsigned short) (sr_data & 0x03) << 6);
-
-      /* Horizontal retrace (=sync) end */
-      HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
-      temp = HBE - ((E - 1) & 255);
-      B = (temp > 0) ? temp : (temp + 256);
-
-      temp = HRE - ((E + F + 3) & 63);
-      C = (temp > 0) ? temp : (temp + 64); /* 0x0b 0x0b */
-
-      D = B - F - C;
-
-      if((pSiS->SiS_Pr->SiS_RefIndex[i].XRes == 320) &&
-        ((pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 200) ||
-         (pSiS->SiS_Pr->SiS_RefIndex[i].YRes == 240))) {
-
-        /* Terrible hack, but correct CRTC data for
-         * these modes only produces a black screen...
-         * (HRE is 0, leading into a too large C and
-         * a negative D. The CRT controller does not
-         * seem to like correcting HRE to 50
-         */
-        current->HDisplay   = 320;
-         current->HSyncStart = 328;
-         current->HSyncEnd   = 376;
-         current->HTotal     = 400;
-
-      } else {
-
-         current->HDisplay   = (E * 8);
-         current->HSyncStart = (E * 8) + (F * 8);
-         current->HSyncEnd   = (E * 8) + (F * 8) + (C * 8);
-         current->HTotal     = (E * 8) + (F * 8) + (C * 8) + (D * 8);
-
-      }
-
-#ifdef TWDEBUG
-      xf86DrvMsg(0, X_INFO,
-        "H: A %d B %d C %d D %d E %d F %d  HT %d HDE %d HRS %d HBS %d HBE %d HRE %d\n",
-       A, B, C, D, E, F, HT, HDE, HRS, HBS, HBE, HRE);
-#endif
-
-      sr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[13];
-       /* inSISIDXREG(SISSR, 0x0A, sr_data); */
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[6];
-        /* inSISIDXREG(SISCR, 0x06, cr_data); */
-
-      cr_data2 = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[7];
-        /* inSISIDXREG(SISCR, 0x07, cr_data2);  */
-
-      /* Vertical total */
-      VT = (cr_data & 0xFF) |
-           ((unsigned short) (cr_data2 & 0x01) << 8) |
-          ((unsigned short)(cr_data2 & 0x20) << 4) |
-          ((unsigned short) (sr_data & 0x01) << 10);
-      A = VT + 2;
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[10];
-       /* inSISIDXREG(SISCR, 0x12, cr_data);  */
-
-      /* Vertical display enable end */
-      VDE = (cr_data & 0xff) |
-            ((unsigned short) (cr_data2 & 0x02) << 7) |
-           ((unsigned short) (cr_data2 & 0x40) << 3) |
-           ((unsigned short) (sr_data & 0x02) << 9);
-      E = VDE + 1;
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[8];
-       /* inSISIDXREG(SISCR, 0x10, cr_data); */
-
-      /* Vertical retrace (=sync) start */
-      VRS = (cr_data & 0xff) |
-            ((unsigned short) (cr_data2 & 0x04) << 6) |
-           ((unsigned short) (cr_data2 & 0x80) << 2) |
-           ((unsigned short) (sr_data & 0x08) << 7);
-      F = VRS + 1 - E;
-
-      cr_data =  pSiS->SiS_Pr->SiS_CRT1Table[index].CR[11];
-       /* inSISIDXREG(SISCR, 0x15, cr_data);  */
-
-      cr_data3 = (pSiS->SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5;
-       /* inSISIDXREG(SISCR, 0x09, cr_data3);  */
-
-      /* Vertical blank start */
-      VBS = (cr_data & 0xff) |
-            ((unsigned short) (cr_data2 & 0x08) << 5) |
-           ((unsigned short) (cr_data3 & 0x20) << 4) |
-           ((unsigned short) (sr_data & 0x04) << 8);
-
-      cr_data =  pSiS->SiS_Pr->SiS_CRT1Table[index].CR[12];
-       /* inSISIDXREG(SISCR, 0x16, cr_data); */
-
-      /* Vertical blank end */
-      VBE = (cr_data & 0xff) |
-            ((unsigned short) (sr_data & 0x10) << 4);
-      temp = VBE - ((E - 1) & 511);
-      B = (temp > 0) ? temp : (temp + 512);
-
-      cr_data = pSiS->SiS_Pr->SiS_CRT1Table[index].CR[9];
-       /* inSISIDXREG(SISCR, 0x11, cr_data); */
-
-      /* Vertical retrace (=sync) end */
-      VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
-      temp = VRE - ((E + F - 1) & 31);
-      C = (temp > 0) ? temp : (temp + 32);
-
-      D = B - F - C;
-
-      current->VDisplay   = VDE + 1;
-      current->VSyncStart = VRS + 1;
-      current->VSyncEnd   = ((VRS & ~0x1f) | VRE) + 1;
-      if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
-      current->VTotal     = E + D + C + F;
-
+   /* Vertical */
+   sr_data = crdata[13];
+   cr_data = crdata[7];
+
+   /* Vertical total */
+   VT  = crdata[6] |
+        ((unsigned short)(cr_data & 0x01) << 8) |
+        ((unsigned short)(cr_data & 0x20) << 4) |
+        ((unsigned short)(sr_data & 0x01) << 10);
+   A = VT + 2;
+
+   /* Vertical display enable end */
+   VDE = crdata[10] |
+        ((unsigned short)(cr_data & 0x02) << 7) |
+        ((unsigned short)(cr_data & 0x40) << 3) |
+        ((unsigned short)(sr_data & 0x02) << 9);
+   E = VDE + 1;
+
+   /* Vertical retrace (=sync) start */
+   VRS = crdata[8] |
+        ((unsigned short)(cr_data & 0x04) << 6) |
+        ((unsigned short)(cr_data & 0x80) << 2) |
+        ((unsigned short)(sr_data & 0x08) << 7);
+   F = VRS + 1 - E;
+
+   cr_data2 = (crdata[16] & 0x01) << 5;
+
+   /* Vertical blank start */
+   VBS = crdata[11] |
+        ((unsigned short)(cr_data  & 0x08) << 5) |
+        ((unsigned short)(cr_data2 & 0x20) << 4) |
+        ((unsigned short)(sr_data  & 0x04) << 8);
+
+   /* Vertical blank end */
+   VBE = crdata[12] | ((unsigned short)(sr_data & 0x10) << 4);
+   temp = VBE - ((E - 1) & 511);
+   B = (temp > 0) ? temp : (temp + 512);
+
+   /* Vertical retrace (=sync) end */
+   VRE = (crdata[9] & 0x0f) | ((sr_data & 0x20) >> 1);
+   temp = VRE - ((E + F - 1) & 31);
+   C = (temp > 0) ? temp : (temp + 32);
+
+   D = B - F - C;
+
+#ifdef SIS_XORG_XF86
+   current->VDisplay   = VDE + 1;
+   current->VSyncStart = VRS + 1;
+   current->VSyncEnd   = ((VRS & ~0x1f) | VRE) + 1;
+   if(VRE <= (VRS & 0x1f)) current->VSyncEnd += 32;
+   current->VTotal     = E + D + C + F;
 #if 0
-      current->VDisplay   = E;
-      current->VSyncStart = E + D;
-      current->VSyncEnd   = E + D + C;
-      current->VTotal     = E + D + C + F;
+   current->VDisplay   = E;
+   current->VSyncStart = E + D;
+   current->VSyncEnd   = E + D + C;
+   current->VTotal     = E + D + C + F;
 #endif
-
-#ifdef TWDEBUG
-      xf86DrvMsg(0, X_INFO,
-        "V: A %d B %d C %d D %d E %d F %d  VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
-       A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
-#endif
-
-      if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x4000)
-          current->Flags |= V_NHSYNC;
-      else
-          current->Flags |= V_PHSYNC;
-
-      if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x8000)
-         current->Flags |= V_NVSYNC;
-      else
-          current->Flags |= V_PVSYNC;
-
-      if(pSiS->SiS_Pr->SiS_RefIndex[i].Ext_InfoFlag & 0x0080)
-          current->Flags |= V_INTERLACE;
-
-      j = 0;
-      while(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
-          if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
-                         pSiS->SiS_Pr->SiS_RefIndex[i].ModeID) {
-              if(pSiS->SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
-                 current->Flags |= V_DBLSCAN;
-              }
-             break;
-          }
-         j++;
-      }
-
-      if(current->Flags & V_INTERLACE) {
-         current->VDisplay <<= 1;
-        current->VSyncStart <<= 1;
-        current->VSyncEnd <<= 1;
-        current->VTotal <<= 1;
-        current->VTotal |= 1;
-      }
-      if(current->Flags & V_DBLSCAN) {
-         current->Clock >>= 1;
-        current->VDisplay >>= 1;
-        current->VSyncStart >>= 1;
-        current->VSyncEnd >>= 1;
-        current->VTotal >>= 1;
-      }
-
 #ifdef TWDEBUG
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-       "Built-in: %s %.2f %d %d %d %d %d %d %d %d\n",
-       current->name, (float)current->Clock / 1000,
-       current->HDisplay, current->HSyncStart, current->HSyncEnd, current->HTotal,
-       current->VDisplay, current->VSyncStart, current->VSyncEnd, current->VTotal);
-#else
-        (void)VBS;  (void)HBS;  (void)A;
+   xf86DrvMsg(0, X_INFO,
+       "V: A %d B %d C %d D %d E %d F %d  VT %d VDE %d VRS %d VBS %d VBE %d VRE %d\n",
+       A, B, C, D, E, F, VT, VDE, VRS, VBS, VBE, VRE);
 #endif
-
-      i++;
-   }
-
-   /* Add non-standard LCD modes for panel's detailed timings */
-
-   if(!includelcdmodes) return first;
-
-   if(pSiS->SiS_Pr->CP_Vendor) {
-      xf86DrvMsg(0, X_INFO, "Checking database for vendor %x, product %x\n",
-         pSiS->SiS_Pr->CP_Vendor, pSiS->SiS_Pr->CP_Product);
-   }
-
-   i = 0;
-   while((!done) && (SiS_PlasmaTable[i].vendor) && (pSiS->SiS_Pr->CP_Vendor)) {
-
-     if(SiS_PlasmaTable[i].vendor == pSiS->SiS_Pr->CP_Vendor) {
-
-        for(j=0; j<SiS_PlasmaTable[i].productnum; j++) {
-
-           if(SiS_PlasmaTable[i].product[j] == pSiS->SiS_Pr->CP_Product) {
-
-              xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-                 "Identified %s panel, adding specific modes\n",
-                 SiS_PlasmaTable[i].plasmaname);
-
-              for(k=0; k<SiS_PlasmaTable[i].modenum; k++) {
-
-                 if(isfordvi) {
-                    if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x80)) continue;
-                 } else {
-                    if(!(SiS_PlasmaTable[i].plasmamodes[k] & 0x40)) continue;
-                 }
-
-                 l = SiS_PlasmaTable[i].plasmamodes[k] & 0x3f;
-
-                 if(pSiS->VBFlags & (VB_301|VB_301B|VB_302B|VB_301LV)) {
-                    if(isfordvi) {
-                       if(SiS_PlasmaMode[l].VDisplay > 1024) continue;
-                    }
-                 }
-
-                 if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-
-                  memset(new, 0, sizeof(DisplayModeRec));
-                  if(!(new->name = xalloc(12))) {
-                    xfree(new);
-                    return first;
-                  }
-                  if(!first) first = new;
-                  if(current) {
-                     current->next = new;
-                    new->prev = current;
-                  }
-
-                  current = new;
-
-                 pSiS->AddedPlasmaModes = TRUE;
-
-                 strcpy(current->name, SiS_PlasmaMode[l].name);
-                 /* sprintf(current->name, "%dx%d", SiS_PlasmaMode[l].HDisplay,
-                                                  SiS_PlasmaMode[l].VDisplay); */
-
-                  current->status = MODE_OK;
-
-                  current->type = M_T_BUILTIN;
-
-                 current->Clock = SiS_PlasmaMode[l].clock;
-                 current->SynthClock = current->Clock;
-
-                  current->HDisplay   = SiS_PlasmaMode[l].HDisplay;
-                  current->HSyncStart = current->HDisplay + SiS_PlasmaMode[l].HFrontPorch;
-                  current->HSyncEnd   = current->HSyncStart + SiS_PlasmaMode[l].HSyncWidth;
-                  current->HTotal     = SiS_PlasmaMode[l].HTotal;
-
-                 current->VDisplay   = SiS_PlasmaMode[l].VDisplay;
-                  current->VSyncStart = current->VDisplay + SiS_PlasmaMode[l].VFrontPorch;
-                  current->VSyncEnd   = current->VSyncStart + SiS_PlasmaMode[l].VSyncWidth;
-                  current->VTotal     = SiS_PlasmaMode[l].VTotal;
-
-                  current->CrtcHDisplay = current->HDisplay;
-                  current->CrtcHBlankStart = current->HSyncStart;
-                  current->CrtcHSyncStart = current->HSyncStart;
-                  current->CrtcHSyncEnd = current->HSyncEnd;
-                  current->CrtcHBlankEnd = current->HSyncEnd;
-                  current->CrtcHTotal = current->HTotal;
-
-                  current->CrtcVDisplay = current->VDisplay;
-                  current->CrtcVBlankStart = current->VSyncStart;
-                  current->CrtcVSyncStart = current->VSyncStart;
-                  current->CrtcVSyncEnd = current->VSyncEnd;
-                  current->CrtcVBlankEnd = current->VSyncEnd;
-                  current->CrtcVTotal = current->VTotal;
-
-                  if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_HSYNCP)
-                     current->Flags |= V_PHSYNC;
-                  else
-                     current->Flags |= V_NHSYNC;
-
-                  if(SiS_PlasmaMode[l].SyncFlags & SIS_PL_VSYNCP)
-                     current->Flags |= V_PVSYNC;
-                  else
-                     current->Flags |= V_NVSYNC;
-
-                 if(current->HDisplay > pSiS->LCDwidth)
-                    pSiS->LCDwidth = pSiS->SiS_Pr->CP_MaxX = current->HDisplay;
-                 if(current->VDisplay > pSiS->LCDheight)
-                    pSiS->LCDheight = pSiS->SiS_Pr->CP_MaxY = current->VDisplay;
-
-                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
-                       "\tAdding \"%s\" to list of built-in modes\n", current->name);
-
-               }
-              done = TRUE;
-              break;
-           }
-       }
-     }
-
-     i++;
-
-   }
-
-   if(pSiS->SiS_Pr->CP_HaveCustomData) {
-
-      for(i=0; i<7; i++) {
-
-         if(pSiS->SiS_Pr->CP_DataValid[i]) {
-
-            if(!(new = xalloc(sizeof(DisplayModeRec)))) return first;
-
-            memset(new, 0, sizeof(DisplayModeRec));
-            if(!(new->name = xalloc(10))) {
-               xfree(new);
-               return first;
-            }
-            if(!first) first = new;
-            if(current) {
-               current->next = new;
-              new->prev = current;
-            }
-
-            current = new;
-
-            sprintf(current->name, "%dx%d", pSiS->SiS_Pr->CP_HDisplay[i],
-                                            pSiS->SiS_Pr->CP_VDisplay[i]);
-
-            current->status = MODE_OK;
-
-            current->type = M_T_BUILTIN;
-
-            current->Clock = pSiS->SiS_Pr->CP_Clock[i];
-            current->SynthClock = current->Clock;
-
-            current->HDisplay   = pSiS->SiS_Pr->CP_HDisplay[i];
-            current->HSyncStart = pSiS->SiS_Pr->CP_HSyncStart[i];
-            current->HSyncEnd   = pSiS->SiS_Pr->CP_HSyncEnd[i];
-            current->HTotal     = pSiS->SiS_Pr->CP_HTotal[i];
-
-            current->VDisplay   = pSiS->SiS_Pr->CP_VDisplay[i];
-            current->VSyncStart = pSiS->SiS_Pr->CP_VSyncStart[i];
-            current->VSyncEnd   = pSiS->SiS_Pr->CP_VSyncEnd[i];
-            current->VTotal     = pSiS->SiS_Pr->CP_VTotal[i];
-
-            current->CrtcHDisplay = current->HDisplay;
-            current->CrtcHBlankStart = pSiS->SiS_Pr->CP_HBlankStart[i];
-            current->CrtcHSyncStart = current->HSyncStart;
-            current->CrtcHSyncEnd = current->HSyncEnd;
-            current->CrtcHBlankEnd = pSiS->SiS_Pr->CP_HBlankEnd[i];
-            current->CrtcHTotal = current->HTotal;
-
-            current->CrtcVDisplay = current->VDisplay;
-            current->CrtcVBlankStart = pSiS->SiS_Pr->CP_VBlankStart[i];
-            current->CrtcVSyncStart = current->VSyncStart;
-            current->CrtcVSyncEnd = current->VSyncEnd;
-            current->CrtcVBlankEnd = pSiS->SiS_Pr->CP_VBlankEnd[i];
-            current->CrtcVTotal = current->VTotal;
-
-           if(pSiS->SiS_Pr->CP_SyncValid[i]) {
-               if(pSiS->SiS_Pr->CP_HSync_P[i])
-                  current->Flags |= V_PHSYNC;
-               else
-                  current->Flags |= V_NHSYNC;
-
-               if(pSiS->SiS_Pr->CP_VSync_P[i])
-                  current->Flags |= V_PVSYNC;
-               else
-                  current->Flags |= V_NVSYNC;
-           } else {
-              /* No sync data? Use positive sync... */
-              current->Flags |= V_PHSYNC;
-              current->Flags |= V_PVSYNC;
-           }
-         }
-      }
-   }
-
-   return first;
-
-}
-
-/* Translate a mode number into the VESA pendant */
-int
-SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber)
-{
-   SISPtr pSiS = SISPTR(pScrn);
-   int    i = 0;
-
-   /* Initialize our pointers */
-   if(pSiS->VGAEngine == SIS_300_VGA) {
-#ifdef SIS300
-       InitTo300Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
-       return -1;
 #endif
-   } else if(pSiS->VGAEngine == SIS_315_VGA) {
-#ifdef SIS315H
-               InitTo310Pointer(pSiS->SiS_Pr, &pSiS->sishw_ext);
-#else
-       return -1;
+#ifdef SIS_LINUX_KERNEL
+   if(writeres) var->yres = yres = E;
+   var->upper_margin = D;
+   var->lower_margin = F;
+   var->vsync_len = C;
 #endif
-   } else return -1;
-
-   if(modenumber <= 0x13) return modenumber;
 
-#ifdef SIS315H
-   if(pSiS->ROM661New) {
-      while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) {
-         if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) {
-            return (int)SiS_EModeIDTable661[i].Ext_VESAID;
-         }
-         i++;
-      }
-   } else {
+   if((xres == 320) && ((yres == 200) || (yres == 240))) {
+       /* Terrible hack, but correct CRTC data for
+        * these modes only produces a black screen...
+        * (HRE is 0, leading into a too large C and
+        * a negative D. The CRT controller does not
+        * seem to like correcting HRE to 50)
+        */
+#ifdef SIS_XORG_XF86
+      current->HDisplay   = 320;
+      current->HSyncStart = 328;
+      current->HSyncEnd   = 376;
+      current->HTotal     = 400;
 #endif
-      while(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID != 0xff) {
-         if(pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_ModeID == modenumber) {
-            return (int)pSiS->SiS_Pr->SiS_EModeIDTable[i].Ext_VESAID;
-         }
-         i++;
-      }
-#ifdef SIS315H
-   }
+#ifdef SIS_LINUX_KERNEL
+      var->left_margin = (400 - 376);
+      var->right_margin = (328 - 320);
+      var->hsync_len = (376 - 328);
 #endif
-   return -1;
-}
 
-/* Translate a new BIOS mode number into the driver's pendant */
-int
-SiSTranslateToOldMode(int modenumber)
-{
-#ifdef SIS315H
-   int    i = 0;
-
-   while(SiS_EModeIDTable661[i].Ext_ModeID != 0xff) {
-      if(SiS_EModeIDTable661[i].Ext_ModeID == modenumber) {
-         if(SiS_EModeIDTable661[i].Ext_MyModeID)
-            return (int)SiS_EModeIDTable661[i].Ext_MyModeID;
-        else
-           return modenumber;
-      }
-      i++;
    }
-#endif
-   return modenumber;
-}
-
-#endif  /* Xfree86 */
 
-#ifdef LINUX_KERNEL
-int
-sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                         unsigned char modeno, unsigned char rateindex)
-{
-    USHORT ModeNo = modeno;
-    USHORT ModeIdIndex = 0, ClockIndex = 0;
-    USHORT RefreshRateTableIndex = 0;
-    int    Clock;
-
-    if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
-       InitTo300Pointer(SiS_Pr, HwInfo);
-#else
-       return 65 * 1000;
-#endif
-    } else {
-#ifdef SIS315H
-       InitTo310Pointer(SiS_Pr, HwInfo);
-#else
-       return 65 * 1000;
-#endif
-    }
-
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
-       printk(KERN_ERR "Could not find mode %x\n", ModeNo);
-       return 65 * 1000;
-    }
-
-    RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-    RefreshRateTableIndex += (rateindex - 1);
-    ClockIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-    if(HwInfo->jChipType < SIS_315H) {
-       ClockIndex &= 0x3F;
-    }
-    Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
-    
-    return(Clock);
 }
 
-BOOLEAN
-sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                      unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex)
-{
-    USHORT ModeNo = modeno;
-    USHORT ModeIdIndex = 0, CRT1Index = 0;
-    USHORT RefreshRateTableIndex = 0;
-    unsigned char  sr_data, cr_data, cr_data2;
-
-    if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
-       InitTo300Pointer(SiS_Pr, HwInfo);
-#else
-       return FALSE;
-#endif
-    } else {
-#ifdef SIS315H
-       InitTo310Pointer(SiS_Pr, HwInfo);
-#else
-       return FALSE;
-#endif
-    }
-
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
-
-    RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-    RefreshRateTableIndex += (rateindex - 1);
-    CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
-    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
-    *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
 
-    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
-    cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-    *vtotal = ((cr_data & 0xFF) |
-               ((unsigned short)(cr_data2 & 0x01) <<  8) |
-              ((unsigned short)(cr_data2 & 0x20) <<  4) |
-              ((unsigned short)(sr_data  & 0x01) << 10)) + 2;
 
-    if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & InterlaceMode)
-       *vtotal *= 2;
-
-    return TRUE;
-}
-
-int
-sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                        unsigned char modeno, unsigned char rateindex,
-                        struct fb_var_screeninfo *var)
-{
-    USHORT ModeNo = modeno;
-    USHORT ModeIdIndex = 0, index = 0;
-    USHORT RefreshRateTableIndex = 0;
-    unsigned short VRE, VBE, VRS, VBS, VDE, VT;
-    unsigned short HRE, HBE, HRS, HBS, HDE, HT;
-    unsigned char  sr_data, cr_data, cr_data2, cr_data3;
-    int            A, B, C, D, E, F, temp, j;
-   
-    if(HwInfo->jChipType < SIS_315H) {
-#ifdef SIS300
-       InitTo300Pointer(SiS_Pr, HwInfo);
-#else
-       return 0;
-#endif
-    } else {
-#ifdef SIS315H
-       InitTo310Pointer(SiS_Pr, HwInfo);
-#else
-       return 0;
-#endif
-    }
-
-    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
-
-    RefreshRateTableIndex = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-    RefreshRateTableIndex += (rateindex - 1);
-    index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-
-    sr_data = SiS_Pr->SiS_CRT1Table[index].CR[14];
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[0];
-
-    /* Horizontal total */
-    HT = (cr_data & 0xff) |
-         ((unsigned short) (sr_data & 0x03) << 8);
-    A = HT + 5;
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[1];
-       
-    /* Horizontal display enable end */
-    HDE = (cr_data & 0xff) |
-          ((unsigned short) (sr_data & 0x0C) << 6);
-    E = HDE + 1;
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[4];
-       
-    /* Horizontal retrace (=sync) start */
-    HRS = (cr_data & 0xff) |
-          ((unsigned short) (sr_data & 0xC0) << 2);
-    F = HRS - E - 3;
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[2];
-       
-    /* Horizontal blank start */
-    HBS = (cr_data & 0xff) |
-          ((unsigned short) (sr_data & 0x30) << 4);
-
-    sr_data = SiS_Pr->SiS_CRT1Table[index].CR[15];
-       
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[3];
-
-    cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[5];
-       
-    /* Horizontal blank end */
-    HBE = (cr_data & 0x1f) |
-          ((unsigned short) (cr_data2 & 0x80) >> 2) |
-         ((unsigned short) (sr_data & 0x03) << 6);
-
-    /* Horizontal retrace (=sync) end */
-    HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
-    temp = HBE - ((E - 1) & 255);
-    B = (temp > 0) ? temp : (temp + 256);
-
-    temp = HRE - ((E + F + 3) & 63);
-    C = (temp > 0) ? temp : (temp + 64);
-
-    D = B - F - C;
-
-    if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes == 320) &&
-       ((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 200) ||
-       (SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].YRes == 240))) {
-
-        /* Terrible hack, but the correct CRTC data for
-         * these modes only produces a black screen...
-         */
-       var->left_margin = (400 - 376);
-       var->right_margin = (328 - 320);
-       var->hsync_len = (376 - 328);
-
-    } else {
-
-       var->left_margin = D * 8;
-       var->right_margin = F * 8;
-       var->hsync_len = C * 8;
-
-    }
-
-    sr_data = SiS_Pr->SiS_CRT1Table[index].CR[13];
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[6];
-
-    cr_data2 = SiS_Pr->SiS_CRT1Table[index].CR[7];
-
-    /* Vertical total */
-    VT = (cr_data & 0xFF) |
-         ((unsigned short) (cr_data2 & 0x01) << 8) |
-        ((unsigned short)(cr_data2 & 0x20) << 4) |
-        ((unsigned short) (sr_data & 0x01) << 10);
-    A = VT + 2;
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[10];
-       
-    /* Vertical display enable end */
-    VDE = (cr_data & 0xff) |
-          ((unsigned short) (cr_data2 & 0x02) << 7) |
-         ((unsigned short) (cr_data2 & 0x40) << 3) |
-         ((unsigned short) (sr_data & 0x02) << 9);
-    E = VDE + 1;
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[8];
-
-    /* Vertical retrace (=sync) start */
-    VRS = (cr_data & 0xff) |
-          ((unsigned short) (cr_data2 & 0x04) << 6) |
-         ((unsigned short) (cr_data2 & 0x80) << 2) |
-         ((unsigned short) (sr_data & 0x08) << 7);
-    F = VRS + 1 - E;
-
-    cr_data =  SiS_Pr->SiS_CRT1Table[index].CR[11];
-
-    cr_data3 = (SiS_Pr->SiS_CRT1Table[index].CR[16] & 0x01) << 5;
-
-    /* Vertical blank start */
-    VBS = (cr_data & 0xff) |
-          ((unsigned short) (cr_data2 & 0x08) << 5) |
-         ((unsigned short) (cr_data3 & 0x20) << 4) |
-         ((unsigned short) (sr_data & 0x04) << 8);
-
-    cr_data =  SiS_Pr->SiS_CRT1Table[index].CR[12];
-
-    /* Vertical blank end */
-    VBE = (cr_data & 0xff) |
-          ((unsigned short) (sr_data & 0x10) << 4);
-    temp = VBE - ((E - 1) & 511);
-    B = (temp > 0) ? temp : (temp + 512);
-
-    cr_data = SiS_Pr->SiS_CRT1Table[index].CR[9];
-
-    /* Vertical retrace (=sync) end */
-    VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
-    temp = VRE - ((E + F - 1) & 31);
-    C = (temp > 0) ? temp : (temp + 32);
-
-    D = B - F - C;
-      
-    var->upper_margin = D;
-    var->lower_margin = F;
-    var->vsync_len = C;
-
-    if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
-       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
-    else
-       var->sync |= FB_SYNC_VERT_HIGH_ACT;
-
-    if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)       
-       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
-    else
-       var->sync |= FB_SYNC_HOR_HIGH_ACT;
-               
-    var->vmode = FB_VMODE_NONINTERLACED;
-    if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
-       var->vmode = FB_VMODE_INTERLACED;
-    else {
-       j = 0;
-       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
-          if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
-                         SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) {
-              if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
-                 var->vmode = FB_VMODE_DOUBLE;
-              }
-             break;
-          }
-         j++;
-       }
-    }       
-
-    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-#if 0  /* Do this? */
-       var->upper_margin <<= 1;
-       var->lower_margin <<= 1;
-       var->vsync_len <<= 1;
-#endif
-    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-       var->upper_margin >>= 1;
-       var->lower_margin >>= 1;
-       var->vsync_len >>= 1;
-    }
-
-    return 1;       
-}                        
-
-#endif
 
index 7e36b7ac1470570b4fc43e9b4168bd36b0a98e94..634c0a9d219b1a1da486c76633deb21c41f8c2a0 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * Data and prototypes for init.c
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-#ifndef _INIT_
-#define _INIT_
+#ifndef _INIT_H_
+#define _INIT_H_
 
 #include "osdef.h"
 #include "initdef.h"
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 #include "sis.h"
+#define SIS_NEED_inSISREG
+#define SIS_NEED_inSISREGW
+#define SIS_NEED_inSISREGL
+#define SIS_NEED_outSISREG
+#define SIS_NEED_outSISREGW
+#define SIS_NEED_outSISREGL
 #include "sis_regs.h"
 #endif
 
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
 #include "vgatypes.h"
 #include "vstruct.h"
 #ifdef SIS_CP
 #include <asm/io.h>
 #include <linux/fb.h>
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#endif
+#include "sis.h"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <linux/sisfb.h>
 #else
 #include <video/sisfb.h>
 #endif
 
 /* Mode numbers */
-static const USHORT ModeIndex_320x200[]      = {0x59, 0x41, 0x00, 0x4f};
-static const USHORT ModeIndex_320x240[]      = {0x50, 0x56, 0x00, 0x53};
-static const USHORT ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00};  /* FSTN */
-static const USHORT ModeIndex_400x300[]      = {0x51, 0x57, 0x00, 0x54};
-static const USHORT ModeIndex_512x384[]      = {0x52, 0x58, 0x00, 0x5c};
-static const USHORT ModeIndex_640x400[]      = {0x2f, 0x5d, 0x00, 0x5e};
-static const USHORT ModeIndex_640x480[]      = {0x2e, 0x44, 0x00, 0x62};
-static const USHORT ModeIndex_720x480[]      = {0x31, 0x33, 0x00, 0x35};
-static const USHORT ModeIndex_720x576[]      = {0x32, 0x34, 0x00, 0x36};
-static const USHORT ModeIndex_768x576[]      = {0x5f, 0x60, 0x00, 0x61};
-static const USHORT ModeIndex_800x480[]      = {0x70, 0x7a, 0x00, 0x76};
-static const USHORT ModeIndex_800x600[]      = {0x30, 0x47, 0x00, 0x63};
-static const USHORT ModeIndex_848x480[]      = {0x39, 0x3b, 0x00, 0x3e};
-static const USHORT ModeIndex_856x480[]      = {0x3f, 0x42, 0x00, 0x45};
-static const USHORT ModeIndex_960x540[]      = {0x1d, 0x1e, 0x00, 0x1f};  /* 315 series only */
-static const USHORT ModeIndex_960x600[]      = {0x20, 0x21, 0x00, 0x22};  /* 315 series only */
-static const USHORT ModeIndex_1024x768[]     = {0x38, 0x4a, 0x00, 0x64};
-static const USHORT ModeIndex_1024x576[]     = {0x71, 0x74, 0x00, 0x77};
-static const USHORT ModeIndex_1024x600[]     = {0x20, 0x21, 0x00, 0x22};  /* 300 series only */
-static const USHORT ModeIndex_1280x1024[]    = {0x3a, 0x4d, 0x00, 0x65};
-static const USHORT ModeIndex_1280x960[]     = {0x7c, 0x7d, 0x00, 0x7e};
-static const USHORT ModeIndex_1152x768[]     = {0x23, 0x24, 0x00, 0x25};  /* 300 series only */
-static const USHORT ModeIndex_1152x864[]     = {0x29, 0x2a, 0x00, 0x2b};
-static const USHORT ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
-static const USHORT ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
-static const USHORT ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
-static const USHORT ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
-static const USHORT ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
-static const USHORT ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
-static const USHORT ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
-static const USHORT ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
-static const USHORT ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
-static const USHORT ModeIndex_1920x1080[]    = {0x2c, 0x2d, 0x00, 0x73};  /* 315 series only */
-static const USHORT ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
-static const USHORT ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
-static const USHORT ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
-
-static const USHORT SiS_DRAMType[17][5]={
+static const unsigned short ModeIndex_320x200[]      = {0x59, 0x41, 0x00, 0x4f};
+static const unsigned short ModeIndex_320x240[]      = {0x50, 0x56, 0x00, 0x53};
+static const unsigned short ModeIndex_320x240_FSTN[] = {0x5a, 0x5b, 0x00, 0x00};  /* FSTN */
+static const unsigned short ModeIndex_400x300[]      = {0x51, 0x57, 0x00, 0x54};
+static const unsigned short ModeIndex_512x384[]      = {0x52, 0x58, 0x00, 0x5c};
+static const unsigned short ModeIndex_640x400[]      = {0x2f, 0x5d, 0x00, 0x5e};
+static const unsigned short ModeIndex_640x480[]      = {0x2e, 0x44, 0x00, 0x62};
+static const unsigned short ModeIndex_720x480[]      = {0x31, 0x33, 0x00, 0x35};
+static const unsigned short ModeIndex_720x576[]      = {0x32, 0x34, 0x00, 0x36};
+static const unsigned short ModeIndex_768x576[]      = {0x5f, 0x60, 0x00, 0x61};
+static const unsigned short ModeIndex_800x480[]      = {0x70, 0x7a, 0x00, 0x76};
+static const unsigned short ModeIndex_800x600[]      = {0x30, 0x47, 0x00, 0x63};
+static const unsigned short ModeIndex_848x480[]      = {0x39, 0x3b, 0x00, 0x3e};
+static const unsigned short ModeIndex_856x480[]      = {0x3f, 0x42, 0x00, 0x45};
+static const unsigned short ModeIndex_960x540[]      = {0x1d, 0x1e, 0x00, 0x1f};  /* 315 series only */
+static const unsigned short ModeIndex_960x600[]      = {0x20, 0x21, 0x00, 0x22};  /* 315 series only */
+static const unsigned short ModeIndex_1024x768[]     = {0x38, 0x4a, 0x00, 0x64};
+static const unsigned short ModeIndex_1024x576[]     = {0x71, 0x74, 0x00, 0x77};
+static const unsigned short ModeIndex_1024x600[]     = {0x20, 0x21, 0x00, 0x22};  /* 300 series only */
+static const unsigned short ModeIndex_1280x1024[]    = {0x3a, 0x4d, 0x00, 0x65};
+static const unsigned short ModeIndex_1280x960[]     = {0x7c, 0x7d, 0x00, 0x7e};
+static const unsigned short ModeIndex_1152x768[]     = {0x23, 0x24, 0x00, 0x25};  /* 300 series only */
+static const unsigned short ModeIndex_1152x864[]     = {0x29, 0x2a, 0x00, 0x2b};
+static const unsigned short ModeIndex_300_1280x768[] = {0x55, 0x5a, 0x00, 0x5b};
+static const unsigned short ModeIndex_310_1280x768[] = {0x23, 0x24, 0x00, 0x25};
+static const unsigned short ModeIndex_1280x720[]     = {0x79, 0x75, 0x00, 0x78};
+static const unsigned short ModeIndex_1280x800[]     = {0x14, 0x15, 0x00, 0x16};
+static const unsigned short ModeIndex_1280x854[]     = {0x1a, 0x1b, 0x00, 0x1c};
+static const unsigned short ModeIndex_1360x768[]     = {0x48, 0x4b, 0x00, 0x4e};
+static const unsigned short ModeIndex_300_1360x1024[]= {0x67, 0x6f, 0x00, 0x72};  /* 300 series, BARCO only */
+static const unsigned short ModeIndex_1400x1050[]    = {0x26, 0x27, 0x00, 0x28};  /* 315 series only */
+static const unsigned short ModeIndex_1680x1050[]    = {0x17, 0x18, 0x00, 0x19};  /* 315 series only */
+static const unsigned short ModeIndex_1600x1200[]    = {0x3c, 0x3d, 0x00, 0x66};
+static const unsigned short ModeIndex_1920x1080[]    = {0x2c, 0x2d, 0x00, 0x73};  /* 315 series only */
+static const unsigned short ModeIndex_1920x1440[]    = {0x68, 0x69, 0x00, 0x6b};
+static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
+static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
+
+static const unsigned short SiS_DRAMType[17][5]={
        {0x0C,0x0A,0x02,0x40,0x39},
        {0x0D,0x0A,0x01,0x40,0x48},
        {0x0C,0x09,0x02,0x20,0x35},
@@ -137,7 +148,7 @@ static const USHORT SiS_DRAMType[17][5]={
        {0x09,0x08,0x01,0x01,0x00}
 };
 
-static const USHORT SiS_SDRDRAM_TYPE[13][5] =
+static const unsigned short SiS_SDRDRAM_TYPE[13][5] =
 {
        { 2,12, 9,64,0x35},
        { 1,13, 9,64,0x44},
@@ -154,7 +165,7 @@ static const USHORT SiS_SDRDRAM_TYPE[13][5] =
        { 1, 9, 8, 2,0x00}
 };
 
-static const USHORT SiS_DDRDRAM_TYPE[4][5] =
+static const unsigned short SiS_DDRDRAM_TYPE[4][5] =
 {
        { 2,12, 9,64,0x35},
        { 2,12, 8,32,0x31},
@@ -162,7 +173,7 @@ static const USHORT SiS_DDRDRAM_TYPE[4][5] =
        { 2, 9, 8, 4,0x01}
 };
 
-static const USHORT SiS_MDA_DAC[] =
+static const unsigned char SiS_MDA_DAC[] =
 {
        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
         0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
@@ -174,7 +185,7 @@ static const USHORT SiS_MDA_DAC[] =
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
 };
 
-static const USHORT SiS_CGA_DAC[] =
+static const unsigned char SiS_CGA_DAC[] =
 {
         0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
         0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
@@ -186,7 +197,7 @@ static const USHORT SiS_CGA_DAC[] =
         0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
 };
 
-static const USHORT SiS_EGA_DAC[] =
+static const unsigned char SiS_EGA_DAC[] =
 {
         0x00,0x10,0x04,0x14,0x01,0x11,0x05,0x15,
         0x20,0x30,0x24,0x34,0x21,0x31,0x25,0x35,
@@ -198,7 +209,7 @@ static const USHORT SiS_EGA_DAC[] =
         0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F
 };
 
-static const USHORT SiS_VGA_DAC[] =
+static const unsigned char SiS_VGA_DAC[] =
 {
        0x00,0x10,0x04,0x14,0x01,0x11,0x09,0x15,
        0x2A,0x3A,0x2E,0x3E,0x2B,0x3B,0x2F,0x3F,
@@ -212,7 +223,31 @@ static const USHORT SiS_VGA_DAC[] =
        0x0B,0x0C,0x0D,0x0F,0x10
 };
 
-static const SiS_StResInfoStruct SiS_StResInfo[]=
+static const struct SiS_St SiS_SModeIDTable[] =
+{
+       {0x01,0x9208,0x01,0x00,0x00,0x00,0x01,0x00,0x40},
+       {0x01,0x1210,0x14,0x01,0x01,0x00,0x01,0x00,0x40},
+       {0x01,0x1010,0x17,0x02,0x02,0x00,0x01,0x01,0x40},
+       {0x03,0x8208,0x03,0x00,0x00,0x00,0x01,0x02,0x40},
+       {0x03,0x0210,0x16,0x01,0x01,0x00,0x01,0x02,0x40},
+       {0x03,0x0010,0x18,0x02,0x02,0x00,0x01,0x03,0x40},
+       {0x05,0x9209,0x05,0x00,0x00,0x00,0x00,0x04,0x40},
+       {0x06,0x8209,0x06,0x00,0x00,0x00,0x00,0x05,0x40},
+       {0x07,0x0000,0x07,0x03,0x03,0x00,0x01,0x03,0x40},
+       {0x07,0x0000,0x19,0x02,0x02,0x00,0x01,0x03,0x40},
+       {0x0d,0x920a,0x0d,0x00,0x00,0x00,0x00,0x04,0x40},
+       {0x0e,0x820a,0x0e,0x00,0x00,0x00,0x00,0x05,0x40},
+       {0x0f,0x0202,0x11,0x01,0x01,0x00,0x00,0x05,0x40},
+       {0x10,0x0212,0x12,0x01,0x01,0x00,0x00,0x05,0x40},
+       {0x11,0x0212,0x1a,0x04,0x04,0x00,0x00,0x05,0x40},
+       {0x12,0x0212,0x1b,0x04,0x04,0x00,0x00,0x05,0x40},
+       {0x13,0x021b,0x1c,0x00,0x00,0x00,0x00,0x04,0x40},
+       {0x12,0x0010,0x18,0x02,0x02,0x00,0x00,0x05,0x40},
+       {0x12,0x0210,0x18,0x01,0x01,0x00,0x00,0x05,0x40},
+       {0xff,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+};
+
+static const struct SiS_StResInfo_S SiS_StResInfo[]=
 {
        { 640,400},
        { 640,350},
@@ -221,7 +256,7 @@ static const SiS_StResInfoStruct SiS_StResInfo[]=
        { 640,480}
 };
 
-static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
+static const struct SiS_ModeResInfo_S SiS_ModeResInfo[] =
 {
        {  320, 200, 8, 8},   /* 0x00 */
        {  320, 240, 8, 8},   /* 0x01 */
@@ -256,11 +291,12 @@ static const SiS_ModeResInfoStruct SiS_ModeResInfo[] =
        { 1280, 800, 8,16},   /* 0x1e */
        { 1920,1080, 8,16},   /* 0x1f */
        {  960, 540, 8,16},   /* 0x20 */
-       {  960, 600, 8,16}    /* 0x21 */
+       {  960, 600, 8,16},   /* 0x21 */
+       { 1280, 854, 8,16}    /* 0x22 */
 };
 
 #if defined(SIS300) || defined(SIS315H)
-static const SiS_StandTableStruct SiS_StandTable[]=
+static const struct SiS_StandTable_S SiS_StandTable[]=
 {
 /* 0x00: MD_0_200 */
  {
@@ -704,11 +740,11 @@ static const SiS_StandTableStruct SiS_StandTable[]=
 /* SIS VIDEO BRIDGE ----------------------------------------- */
 /**************************************************************/
 
-static const UCHAR SiS_SoftSetting  = 0x30;   /* RAM setting */
+static const unsigned char SiS_SoftSetting  = 0x30;   /* RAM setting */
 
-static const UCHAR SiS_OutputSelect = 0x40;
+static const unsigned char SiS_OutputSelect = 0x40;
 
-static const UCHAR SiS_NTSCTiming[] = {
+static const unsigned char SiS_NTSCTiming[] = {
        0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
        0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
        0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
@@ -719,7 +755,7 @@ static const UCHAR SiS_NTSCTiming[] = {
        0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
 };
 
-static const UCHAR SiS_PALTiming[] = {
+static const unsigned char SiS_PALTiming[] = {
        0x19,0x52,0x35,0x6e,0x04,0x38,0x3d,0x70,
        0x94,0x49,0x01,0x12,0x06,0x3e,0x35,0x6d,
        0x06,0x14,0x3e,0x35,0x6d,0x00,0x45,0x2b,
@@ -730,8 +766,8 @@ static const UCHAR SiS_PALTiming[] = {
        0x00,0x40,0x3e,0x00,0xe1,0x02,0x28,0x00
 };
 
-static const UCHAR SiS_HiTVExtTiming[] = {
-        0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+static const unsigned char SiS_HiTVExtTiming[] = {
+       0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
        0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
        0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
        0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
@@ -741,8 +777,8 @@ static const UCHAR SiS_HiTVExtTiming[] = {
        0x63,0x4f,0x27,0x00,0xfc,0xff,0x6a,0x00
 };
 
-static const UCHAR SiS_HiTVSt1Timing[] = {
-        0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+static const unsigned char SiS_HiTVSt1Timing[] = {
+       0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
        0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
        0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
        0x65,0x90,0x7b,0xa8,0x03,0xf0,0x87,0x03,
@@ -752,8 +788,8 @@ static const UCHAR SiS_HiTVSt1Timing[] = {
        0xaf,0x5d,0x0e,0x00,0xfc,0xff,0x2d,0x00
 };
 
-static const UCHAR SiS_HiTVSt2Timing[] = {
-        0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
+static const unsigned char SiS_HiTVSt2Timing[] = {
+       0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x64,
        0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
        0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
        0x64,0x90,0x33,0x8c,0x18,0x36,0x3e,0x13,
@@ -764,8 +800,8 @@ static const UCHAR SiS_HiTVSt2Timing[] = {
 };
 
 #if 0
-static const UCHAR SiS_HiTVTextTiming[] = {
-        0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
+static const unsigned char SiS_HiTVTextTiming[] = {
+       0x32,0x65,0x2c,0x5f,0x08,0x31,0x3a,0x65,
        0x28,0x02,0x01,0x3d,0x06,0x3e,0x35,0x6d,
        0x06,0x14,0x3e,0x35,0x6d,0x00,0xc5,0x3f,
        0x65,0x90,0xe7,0xbc,0x03,0x0c,0x97,0x03,
@@ -776,8 +812,8 @@ static const UCHAR SiS_HiTVTextTiming[] = {
 };
 #endif
 
-static const UCHAR SiS_HiTVGroup3Data[] = {
-        0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
+static const unsigned char SiS_HiTVGroup3Data[] = {
+       0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x5f,
        0x05,0x21,0xb2,0xb2,0x55,0x77,0x2a,0xa6,
        0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
        0x8c,0x6e,0x60,0x2e,0x58,0x48,0x72,0x44,
@@ -787,8 +823,8 @@ static const UCHAR SiS_HiTVGroup3Data[] = {
        0x18,0x05,0x18,0x05,0x4c,0xa8,0x01
 };
 
-static const UCHAR SiS_HiTVGroup3Simu[] = {
-        0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
+static const unsigned char SiS_HiTVGroup3Simu[] = {
+       0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0x95,
        0xdb,0x20,0xb8,0xb8,0x55,0x47,0x2a,0xa6,
        0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
        0x8c,0x6e,0x60,0x15,0x26,0xd3,0xe4,0x11,
@@ -799,8 +835,8 @@ static const UCHAR SiS_HiTVGroup3Simu[] = {
 };
 
 #if 0
-static const UCHAR SiS_HiTVGroup3Text[] = {
-        0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
+static const unsigned char SiS_HiTVGroup3Text[] = {
+       0x00,0x1a,0x22,0x63,0x62,0x22,0x08,0xa7,
        0xf5,0x20,0xce,0xce,0x55,0x47,0x2a,0xa6,
        0x25,0x2f,0x47,0xfa,0xc8,0xff,0x8e,0x20,
        0x8c,0x6e,0x60,0x18,0x2c,0x0c,0x20,0x22,
@@ -811,136 +847,141 @@ static const UCHAR SiS_HiTVGroup3Text[] = {
 };
 #endif
 
-static const UCHAR SiS_NTSCPhase[]    = {0x21,0xed,0xba,0x08};
-static const UCHAR SiS_PALPhase[]     = {0x2a,0x05,0xe3,0x00};
-static const UCHAR SiS_PALMPhase[]    = {0x21,0xE4,0x2E,0x9B};
-static const UCHAR SiS_PALNPhase[]    = {0x21,0xF4,0x3E,0xBA};
-static const UCHAR SiS_NTSCPhase2[]   = {0x21,0xF0,0x7B,0xD6};
-static const UCHAR SiS_PALPhase2[]    = {0x2a,0x09,0x86,0xe9};
-static const UCHAR SiS_PALMPhase2[]   = {0x21,0xE6,0xEF,0xA4};
-static const UCHAR SiS_PALNPhase2[]   = {0x21,0xF6,0x94,0x46};
-static const UCHAR SiS_SpecialPhase[] = {0x1e,0x8c,0x5c,0x7a};
-static const UCHAR SiS_SpecialPhaseM[]= {0x1e,0x83,0x0a,0xe0};
-static const UCHAR SiS_SpecialPhaseJ[]= {0x25,0xd4,0xfd,0x5e};
-
-static const SiS_TVDataStruct  SiS_StPALData[] =
+static const struct SiS_TVData SiS_StPALData[] =
 {
- {    1,   1, 864, 525,1270, 400, 100,   0, 760,0xf4,0xff,0x1c,0x22},
- {    1,   1, 864, 525,1270, 350, 100,   0, 760,0xf4,0xff,0x1c,0x22},
- {    1,   1, 864, 525,1270, 400,   0,   0, 720,0xf1,0x04,0x1f,0x18},
- {    1,   1, 864, 525,1270, 350,   0,   0, 720,0xf4,0x0b,0x1c,0x0a},
- {    1,   1, 864, 525,1270, 480,  50,   0, 760,0xf4,0xff,0x1c,0x22},
- {    1,   1, 864, 525,1270, 600,  50,   0,   0,0xf4,0xff,0x1c,0x22}
+ {    1,   1, 864, 525,1270, 400, 100, 0, 760,    0,0xf4,0xff,0x1c,0x22},
+ {    1,   1, 864, 525,1270, 350, 100, 0, 760,    0,0xf4,0xff,0x1c,0x22},
+ {    1,   1, 864, 525,1270, 400,   0, 0, 720,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 864, 525,1270, 350,   0, 0, 720,    0,0xf4,0x0b,0x1c,0x0a},
+ {    1,   1, 864, 525,1270, 480,  50, 0, 760,    0,0xf4,0xff,0x1c,0x22},
+ {    1,   1, 864, 525,1270, 600,  50, 0,   0,0x300,0xf4,0xff,0x1c,0x22}
 };
 
-static const SiS_TVDataStruct  SiS_ExtPALData[] =
+static const struct SiS_TVData SiS_ExtPALData[] =
 {
- {   27,  10, 848, 448,1270, 530,  50,   0,  50,0xf4,0xff,0x1c,0x22},  /* 640x400, 320x200 */
- {  108,  35, 848, 398,1270, 530,  50,   0,  50,0xf4,0xff,0x1c,0x22},
- {   12,   5, 954, 448,1270, 530,  50,   0,  50,0xf1,0x04,0x1f,0x18},
- {    9,   4, 960, 463,1644, 438,  50,   0,  50,0xf4,0x0b,0x1c,0x0a},
- {    9,   4, 848, 528,1270, 530,   0,   0,  50,0xf5,0xfb,0x1b,0x2a},  /* 640x480, 320x240 */
-/*{  36,  25,1060, 648,1316, 530, 438,   0, 438,0xeb,0x05,0x25,0x16},*//* 800x600, 400x300 */
- {   36,  25,1060, 648,1270, 530, 438,   0, 438,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 - better */
- {    3,   2,1080, 619,1270, 540, 438,   0, 438,0xf3,0x00,0x1d,0x20},  /* 720x576 */
- {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 */
- {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
- {    9,   4, 848, 528,1270, 530,   0,   0,  50,0xf5,0xfb,0x1b,0x2a}   /* 720x480 test */
+ {   27,  10, 848, 448,1270, 530,  50, 0,  50,    0,0xf4,0xff,0x1c,0x22},  /* 640x400, 320x200 */
+ {  108,  35, 848, 398,1270, 530,  50, 0,  50,    0,0xf4,0xff,0x1c,0x22},
+ {   12,   5, 954, 448,1270, 530,  50, 0,  50,    0,0xf1,0x04,0x1f,0x18},
+ {    9,   4, 960, 463,1644, 438,  50, 0,  50,    0,0xf4,0x0b,0x1c,0x0a},
+ {    9,   4, 848, 528,1270, 530,   0, 0,  50,    0,0xf5,0xfb,0x1b,0x2a},  /* 640x480, 320x240 */
+ {   36,  25,1060, 648,1270, 530, 438, 0, 438,    0,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 */
+ {    3,   2,1080, 619,1270, 540, 438, 0, 438,    0,0xf3,0x00,0x1d,0x20},  /* 720x576 */
+ {    1,   1,1170, 821,1270, 520, 686, 0, 686,    0,0xF3,0x00,0x1D,0x20},  /* 1024x768 */
+ {    1,   1,1170, 821,1270, 520, 686, 0, 686,    0,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
+ {    9,   4, 848, 528,1270, 530,   0, 0,  50,    0,0xf5,0xfb,0x1b,0x2a}   /* 720x480 */
 };
 
-static const SiS_TVDataStruct  SiS_StNTSCData[] =
+static const struct SiS_TVData SiS_StNTSCData[] =
 {
- {    1,   1, 858, 525,1270, 400,  50,   0, 760,0xf1,0x04,0x1f,0x18},
- {    1,   1, 858, 525,1270, 350,  50,   0, 640,0xf1,0x04,0x1f,0x18},
- {    1,   1, 858, 525,1270, 400,   0,   0, 720,0xf1,0x04,0x1f,0x18},
- {    1,   1, 858, 525,1270, 350,   0,   0, 720,0xf4,0x0b,0x1c,0x0a},
- {    1,   1, 858, 525,1270, 480,   0,   0, 760,0xf1,0x04,0x1f,0x18}
+ {    1,   1, 858, 525,1270, 400,  50, 0, 760,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 858, 525,1270, 350,  50, 0, 640,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 858, 525,1270, 400,   0, 0, 720,    0,0xf1,0x04,0x1f,0x18},
+ {    1,   1, 858, 525,1270, 350,   0, 0, 720,    0,0xf4,0x0b,0x1c,0x0a},
+ {    1,   1, 858, 525,1270, 480,   0, 0, 760,    0,0xf1,0x04,0x1f,0x18}
 };
 
-static const SiS_TVDataStruct  SiS_ExtNTSCData[] =
+static const struct SiS_TVData SiS_ExtNTSCData[] =
 {
- {  143,  65, 858, 443,1270, 440, 171,   0, 171,0xf1,0x04,0x1f,0x18},    /* 640x400, 320x200 */
- {   88,  35, 858, 393,1270, 440, 171,   0, 171,0xf1,0x04,0x1f,0x18},
- {  143,  70, 924, 443,1270, 440,  92,   0,  92,0xf1,0x04,0x1f,0x18},
- {  143,  70, 924, 393,1270, 440,  92,   0,  92,0xf4,0x0b,0x1c,0x0a},
- {  143,  76, 836, 523,1270, 440, 224,   0,   0,0xf1,0x05,0x1f,0x16},    /* 640x480, 320x240 */
- {  143, 120,1056, 643,1270, 440,   0, 128,   0,0xf4,0x10,0x1c,0x00},    /* 800x600, 400x300  */
-/*{   2,   1, 858, 503,1270, 480,   0, 128,   0,0xee,0x0c,0x22,0x08},*/  /* 720x480  (old, from 650) */
- {  143,  76, 836, 523,1270, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
-/*{  65,  64,1056, 791,1270, 480, 638,   0,   0,0xEE,0x0C,0x22,0x08} */  /* 1024x768 (525i) */
- {    1,   1,1100, 811,1412, 440,   0, 128,   0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
- {   65,  64,1056, 791,1270, 480, 455,   0,   0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+ {  143,  65, 858, 443,1270, 440, 171, 0, 171,    0,0xf1,0x04,0x1f,0x18},    /* 640x400, 320x200 */
+ {   88,  35, 858, 393,1270, 440, 171, 0, 171,    0,0xf1,0x04,0x1f,0x18},
+ {  143,  70, 924, 443,1270, 440,  92, 0,  92,    0,0xf1,0x04,0x1f,0x18},
+ {  143,  70, 924, 393,1270, 440,  92, 0,  92,    0,0xf4,0x0b,0x1c,0x0a},
+ {  143,  76, 836, 523,1270, 440, 224, 0,   0,    0,0xf1,0x05,0x1f,0x16},    /* 640x480, 320x240 */
+ {  143, 120,1056, 643,1270, 440,   0, 1,   0,    0,0xf4,0x10,0x1c,0x00},    /* 800x600, 400x300  */
+ {  143,  76, 836, 523,1270, 440,   0, 1,   0,    0,0xee,0x0c,0x22,0x08},    /* 720x480 - BETTER (from 300 series) */
+ {    1,   1,1100, 811,1412, 440,   0, 1,   0,    0,0xee,0x0c,0x22,0x08},    /* 1024x768 (525i) CORRECTED */
+#if 0  /* flimmert und ist unten abgeschnitten (NTSCHT, NTSC clock) */
+ {   65,  64,1056, 791,1270, 480, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0
+ {    1,   1,1100, 811,1412, 440,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0
+ {    1,   1,1120, 821,1516, 420,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0
+ {    1,   1, 938, 821,1516, 420,   0, 1,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0 /* zoom hin, unten abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ {    1,   1,1072, 791,1270, 480, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 1 /* zu weit links (squeezed) (NTSC2HT, NTSC1024 clock) */
+ {    1,   1,1100, 846,1270, 440, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
+#if 0 /* zu weit links, rechts abgeschnitten (NTSC2HT, NTSC1024 clock) */
+ {    1,   1,1100, 846,1412, 440, 455, 0,   0,    0,0x00,0x00,0x00,0x00}     /* 1024x768 (525p) */
+#endif
 };
 
-static const SiS_TVDataStruct  SiS_StHiTVData[] =  /* Slave + TVSimu */
+static const struct SiS_TVData SiS_StHiTVData[] =  /* Slave + TVSimu */
 {
- {    1,   1, 0x37c,0x233,0x2b2,0x320,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x37c,0x233,0x2b2,0x320,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x37c,0x233,0x2b2,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x150,128, 0, 0x00,0x00,0x00,0x00}
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x320,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x150, 1, 0, 0, 0, 0, 0, 0}
 };
 
-static const SiS_TVDataStruct  SiS_St2HiTVData[] = /* Slave */
+static const struct SiS_TVData SiS_St2HiTVData[] = /* Slave */
 {
- {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,           0,  0, 0, 0x00,0x00,0x00,0x00},
- {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    5,   2, 0x348,0x233,0x670,0x3c0,0x08d,128, 0, 0x00,0x00,0x00,0x00},
- {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x17c,128, 0, 0x00,0x00,0x00,0x00}
+ {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,           0, 0, 0, 0, 0, 0, 0, 0},
+ {    3,   1, 0x348,0x1e3,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x37c,0x233,0x2b2,0x2bc,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    5,   2, 0x348,0x233,0x670,0x3c0,0x08d, 1, 0, 0, 0, 0, 0, 0},
+ {    8,   5, 0x41a,0x2ab,0x670,0x3c0,0x17c, 1, 0, 0, 0, 0, 0, 0}
 };
 
-static const SiS_TVDataStruct  SiS_ExtHiTVData[] =
-{
- {    6,   1, 0x348,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    6,   1, 0x348,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0,  0, 0, 0x00,0x00,0x00,0x00},
- {    5,   1, 0x348,0x233,0x670,0x3c0,0x166,128, 0, 0x00,0x00,0x00,0x00},  /* 640x480   */
- {   16,   5, 0x41a,0x2ab,0x670,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x600   */
- {   25,  12, 0x4ec,0x353,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},  /* 1024x768  */
- {    5,   4, 0x627,0x464,0x670,0x3c0,0x128,  0, 0, 0x00,0x00,0x00,0x00},  /* 1280x1024 */
- {    4,   1, 0x41a,0x233,0x60c,0x3c0,0x143,128, 0, 0x00,0x00,0x00,0x00},  /* 800x480   */
- {    5,   2, 0x578,0x293,0x670,0x3c0,0x032,  0, 0, 0x00,0x00,0x00,0x00},  /* 1024x576  */
- {    8,   5, 0x6d6,0x323,0x670,0x3c0,0x128,  0, 0, 0x00,0x00,0x00,0x00},  /* 1280x720  */
- {  137,  32, 0x3d4,0x233,0x663,0x3bf,0x143,  0, 0, 0x00,0x00,0x00,0x00}   /* 960x600  */
+static const struct SiS_TVData SiS_ExtHiTVData[] =
+{ /* all ok */
+ {    6,   1, 0x348,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    6,   1, 0x348,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    3,   1, 0x3c0,0x233,0x660,0x3c0,    0, 0, 0, 0, 0, 0, 0, 0},
+ {    5,   1, 0x348,0x233,0x670,0x3c0,0x166, 1, 0, 0, 0, 0, 0, 0},  /* 640x480   */
+ {   16,   5, 0x41a,0x2ab,0x670,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0},  /* 800x600   */
+ {   25,  12, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 1024x768  */
+ {    5,   4, 0x627,0x464,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0},  /* 1280x1024 */
+ {    4,   1, 0x41a,0x233,0x60c,0x3c0,0x143, 1, 0, 0, 0, 0, 0, 0},  /* 800x480   */
+ {    5,   2, 0x578,0x293,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 1024x576  */
+ {    8,   5, 0x6d6,0x323,0x670,0x3c0,0x128, 0, 0, 0, 0, 0, 0, 0},  /* 1280x720  */
+ {    8,   3, 0x4ec,0x353,0x670,0x3c0,0x032, 0, 0, 0, 0, 0, 0, 0},  /* 960x600  */
 };
 
-static const SiS_TVDataStruct  SiS_St525pData[] =
+static const struct SiS_TVData SiS_St525pData[] =
 {
- {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x6b4,0x20d,0x4f6,0x1e0,    0,  0, 0x2f8, 0x00,0x00,0x00,0x00}
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
+ {    1,   1, 0x6b4,0x20d,0x4f6,0x1e0,    0, 0, 0x2f8, 0, 0, 0, 0, 0}
 };
 
-static const SiS_TVDataStruct  SiS_St750pData[] =
+static const struct SiS_TVData SiS_St750pData[] =
 {
- {    1,   1, 0x672,0x2ee,0x500,0x190,   50,  0, 0x2f8, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x672,0x2ee,0x500,0x15e,   50,  0, 0x280, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x672,0x2ee,0x500,0x190,    0,  0, 0x2d0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x672,0x2ee,0x500,0x15e,    0,  0, 0x2d0, 0x00,0x00,0x00,0x00},
- {    1,   1, 0x672,0x2ee,0x500,0x1e0,    0,  0, 0x2f8, 0x00,0x00,0x00,0x00}
+ {    1,   1, 0x672,0x2ee,0x500,0x190,   50, 0, 0x2f8, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x15e,   50, 0, 0x280, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x190,    0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x15e,    0, 0, 0x2d0, 0, 0, 0, 0, 0},
+ {    1,   1, 0x672,0x2ee,0x500,0x1e0,    0, 0, 0x2f8, 0, 0, 0, 0, 0}
 };
 
-static const SiS_TVDataStruct  SiS_Ext750pData[] =
-{
- {  143,  65, 0x35a,0x1bb,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
- {   88,  35, 0x35a,0x189,0x4f6,0x1b8,0x0ab,  0, 0x0ab, 0x00,0x00,0x00,0x00},
- {   18,   5, 0x339,0x1ae,0x500,0x2d0,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
- {  143,  70, 0x39c,0x189,0x4f6,0x1b8,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
- {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480  */
- {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600  */
- {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480 test WORKS */
- {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768 */
- {    5,   2, 0x3a7,0x226,0x500,0x2a8,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x576  */
- {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720 WORKS */
+static const struct SiS_TVData SiS_Ext750pData[] =
+{ /* all ok */
+ {    3,  1,  935, 470, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},  /* 320x200/640x400 */
+ {   24,  7,  935, 420, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
+ {    3,  1,  935, 470, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
+ {   24,  7,  935, 420, 1130, 680,  50, 0, 0, 0, 0, 0, 0, 0},
+ {    2,  1, 1100, 590, 1130, 640,  50, 0, 0, 0, 0, 0, 0, 0},  /* 640x480 */
+ {    3,  2, 1210, 690, 1130, 660,  50, 0, 0, 0, 0, 0, 0, 0},  /* 800x600 OK */
+ {    2,  1, 1100, 562, 1130, 640,   0, 1, 0, 0, 0, 0, 0, 0},  /* 720x480 OK */
+ {    1,  1, 1375, 878, 1130, 640, 638, 0, 0, 0, 0, 0, 0, 0},  /* 1024x768 OK */
+ {    5,  3, 1100, 675, 1130, 640,   0, 1, 0, 0, 0, 0, 0, 0},  /* 720/768x576 OK */
+ {   25, 24, 1496, 755, 1120, 680,  50, 0, 0, 0, 0, 0, 0, 0}   /* 1280x720 OK */
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1280x720Data[] =  /* 2.03.00 */
+static const struct SiS_LCDData SiS_LCD1280x720Data[] =  /* 2.03.00 */
 {
        {  44,   15,  864,  430, 1408,  806 }, /* 640x400 */
        { 128,   35,  792,  385, 1408,  806 },
@@ -962,7 +1003,7 @@ static const SiS_LCDDataStruct  SiS_LCD1280x720Data[] =  /* 2.03.00 */
  * (Note: 1280x768_3 is now special for SiS301/NetVista
  */
 
-static const SiS_LCDDataStruct  SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
 {
        {  64,   21,  858,  434, 1408,  806 }, /* 640x400 */
        {  32,    9,  858,  372, 1408,  806 },
@@ -977,7 +1018,7 @@ static const SiS_LCDDataStruct  SiS_StLCD1280x768_2Data[] = /* 2.03.00 */
        {  16,   15, 1600,  750, 1600,  806 }  /* 1280x720 - from Ext */
 };
 
-static const SiS_LCDDataStruct  SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
+static const struct SiS_LCDData SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
 {
        {  16,    5,  960,  410, 1600,  806 }, /* 640x400 */
        {  64,   21, 1152,  364, 1600,  806 },
@@ -993,7 +1034,7 @@ static const SiS_LCDDataStruct  SiS_ExtLCD1280x768_2Data[] = /* 2.03.00 */
 };
 
 #if 0  /* Not used; _3 now reserved for NetVista (SiS301) */
-static const SiS_LCDDataStruct  SiS_LCD1280x768_3Data[] =
+static const struct SiS_LCDData SiS_LCD1280x768_3Data[] =
 {
        {  64,   25, 1056,  422, 1664,  798 },                  /* 640x400 */
        { 128,   39,  884,  396, 1408,  806 }, /* ,640 */
@@ -1009,7 +1050,7 @@ static const SiS_LCDDataStruct  SiS_LCD1280x768_3Data[] =
 };
 #endif
 
-static const SiS_LCDDataStruct  SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
+static const struct SiS_LCDData SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
 {
        { 128,   51, 1122,  412, 1408,  816 },  /* 640x400 */
        { 128,   49, 1232,  361, 1408,  816 },
@@ -1024,7 +1065,7 @@ static const SiS_LCDDataStruct  SiS_LCD1280x800Data[] = /* 0.93.12a (TMDS) */
        {   0,    0,    0,    0,    0,    0 }   /* 1280x720 */
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
+static const struct SiS_LCDData SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
 {
        {  97,   42, 1344,  409, 1552,  812 }, /* 640x400 */
        {  97,   35, 1280,  358, 1552,  812 },
@@ -1039,7 +1080,42 @@ static const SiS_LCDDataStruct  SiS_LCD1280x800_2Data[] = /* 2.03.00 (LVDS) */
        {  97,   90, 1600,  730, 1552,  812 }  /* 1280x720 */
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
+#if 0
+static const struct SiS_LCDData SiS_LCD1280x800_3Data[] = /* 2.02.05a (LVDS); m250 */
+{
+       { 128,   51, 1122,  412, 1408,  816 }, /* 640x400 */
+       { 128,   49, 1232,  361, 1408,  816 },
+       { 128,   51, 1122,  412, 1408,  816 },
+       { 128,   49, 1232,  361, 1408,  816 },
+       {   8,    3,  880,  491, 1408,  816 }, /* 640x480 */
+       {  11,    6, 1024,  612, 1408,  816 }, /* 800x600 */
+       {  22,   21, 1400,  784, 1408,  816 }, /* 1024x768 */
+       {   0,    0,    0,    0,    0,    0 }, /* 1280x1024 */
+       {   1,    1, 1408,  816, 1408,  816 }, /* 1280x800 */
+       {   0,    0,    0,    0,    0,    0 }, /* 1280x768 - patch index */
+       {   0,    0,    0,    0,    0,    0 }  /* 1280x720 */
+};
+#endif
+
+static const struct SiS_LCDData SiS_LCD1280x854Data[] = /* 2.21.00CS (LVDS) */
+{
+       {  56,   15,  936,  410, 1664,  861 },  /* 640x400 */
+       {  64,   25, 1586,  355, 1664,  861 },
+       {  56,   15,  936,  410, 1664,  861 },
+       {  64,   25, 1586,  355, 1664,  861 },
+       {  91,   45, 1464,  485, 1664,  861 },  /* 640x480 */
+       { 182,   75,  976,  605, 1664,  861 },  /* 800x600 */
+       {  91,   66, 1342,  774, 1664,  861 },  /* 1024x768 */
+       {   0,    0,    0,    0,    0,    0 },  /* 1280x1024 */
+       {  26,   25, 1708,  807, 1664,  861 },  /* 1280x800 */
+       {  13,   12, 1708,  774, 1664,  861 },  /* 1280x768 - patch index */
+       {  52,   45, 1708,  725, 1664,  861 },  /* 1280x720 */
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   1,    1, 1664,  861, 1664,  861 }   /* 1280x854 */
+};
+
+static const struct SiS_LCDData SiS_LCD1280x960Data[] =
 {
        {    9,   2,  800,  500, 1800, 1000 },
        {    9,   2,  800,  500, 1800, 1000 },
@@ -1049,10 +1125,15 @@ static const SiS_LCDDataStruct  SiS_LCD1280x960Data[] =
        {   30,  11, 1056,  625, 1800, 1000 },
        {    5,   3, 1350,  800, 1800, 1000 },
        {    1,   1, 1576, 1050, 1576, 1050 },
-       {    1,   1, 1800, 1000, 1800, 1000 }
+       {    1,   1, 1800, 1000, 1800, 1000 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 }
 };
 
-static const SiS_LCDDataStruct  SiS_StLCD1400x1050Data[] =
+static const struct SiS_LCDData SiS_StLCD1400x1050Data[] =
 {
        { 211,  100, 2100,  408, 1688, 1066 },
        { 211,   64, 1536,  358, 1688, 1066 },
@@ -1062,10 +1143,15 @@ static const SiS_LCDDataStruct  SiS_StLCD1400x1050Data[] =
        { 211,   72, 1008,  609, 1688, 1066 },
        { 211,  128, 1400,  776, 1688, 1066 },
        { 211,  205, 1680, 1041, 1688, 1066 },
-       {   1,    1, 1688, 1066, 1688, 1066 }
+       {   1,    1, 1688, 1066, 1688, 1066 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 }
 };
 
-static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
+static const struct SiS_LCDData SiS_ExtLCD1400x1050Data[] =
 {
 /*     { 211,   60, 1260,  410, 1688, 1066 },    640x400 (6330) */
        { 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 (6325) WORKS */
@@ -1080,10 +1166,13 @@ static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
        { 211,  205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
        {   1,    1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
        {   0,    0,    0,    0,    0,    0 }, /* kludge */
-       { 211,  120, 1400,  730, 1688, 1066 }  /* 1280x720 */
+       { 211,  120, 1400,  730, 1688, 1066 }, /* 1280x720 */
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 },
+       {   0,    0,    0,    0,    0,    0 }
 };
 
-static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
+static const struct SiS_LCDData SiS_LCD1680x1050Data[] =
 {
        {  95,   24, 1260,  410, 1900, 1066 }, /*  0 640x400 */
        {  10,    3, 1710,  362, 1900, 1066 },
@@ -1097,10 +1186,11 @@ static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
        {  95,   69, 1800,  817, 1900, 1066 }, /*  9 1280x800 patch index */
        {  13,    9, 1900,  739, 1900, 1066 }, /* 10 1280x720 */
        {  95,   94, 1880, 1066, 1900, 1066 }, /* 11 1400x1050 patch index */
-       {   1,    1, 1900, 1066, 1900, 1066 }  /* 12 1680x1050 */
+       {   1,    1, 1900, 1066, 1900, 1066 }, /* 12 1680x1050 */
+       {   0,    0,    0,    0,    0,    0 }
 };
 
-static const SiS_LCDDataStruct  SiS_StLCD1600x1200Data[] =
+static const struct SiS_LCDData SiS_StLCD1600x1200Data[] =
 {
        {27,  4, 800, 500, 2160, 1250 },
        {27,  4, 800, 500, 2160, 1250 },
@@ -1111,10 +1201,14 @@ static const SiS_LCDDataStruct  SiS_StLCD1600x1200Data[] =
        { 5,  2,1350, 800, 2160, 1250 },
        {135,88,1600,1100, 2160, 1250 },
        {72, 49,1680,1092, 2160, 1250 },
-       { 1,  1,2160,1250, 2160, 1250 }
+       { 1,  1,2160,1250, 2160, 1250 },
+       { 0,  0,   0,   0,    0,    0 },
+       { 0,  0,   0,   0,    0,    0 },
+       { 0,  0,   0,   0,    0,    0 },
+       { 0,  0,   0,   0,    0,    0 }
 };
 
-static const SiS_LCDDataStruct  SiS_ExtLCD1600x1200Data[] =
+static const struct SiS_LCDData SiS_ExtLCD1600x1200Data[] =
 {
        {72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) WORKS */
 /*     {27, 4, 800, 500, 2160, 1250 },    640x400 (6235) */
@@ -1127,10 +1221,14 @@ static const SiS_LCDDataStruct  SiS_ExtLCD1600x1200Data[] =
        { 5, 2,1350, 800, 2160, 1250 },
        {27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
        {72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
-       { 1, 1,2160,1250, 2160, 1250 }
+       { 1, 1,2160,1250, 2160, 1250 },
+       { 0, 0,   0,   0,    0,    0 },
+       { 0, 0,   0,   0,    0,    0 },
+       { 0, 0,   0,   0,    0,    0 },
+       { 0, 0,   0,   0,    0,    0 }
 };
 
-static const SiS_LCDDataStruct  SiS_NoScaleData[] =
+static const struct SiS_LCDData SiS_NoScaleData[] =
 {
        { 1, 1, 800, 449, 800, 449 },  /* 0x00: 320x200, 640x400 */
        { 1, 1, 800, 449, 800, 449 },
@@ -1162,14 +1260,18 @@ static const SiS_LCDDataStruct  SiS_NoScaleData[] =
        { 1, 1,1808, 808,1808, 808 },  /* 0x1b: 1360x768 */
        { 1, 1,1104, 563,1104, 563 },  /* 0x1c: 960x540 */
        { 1, 1,1120, 618,1120, 618 },  /* 0x1d: 960x600 */
-       { 1, 1,1408, 816,1408, 816 }   /* 0x1f: 1280x800 (TMDS special) */
+       { 1, 1,1408, 816,1408, 816 },  /* 0x1f: 1280x800 (TMDS special) */
+       { 1, 1,1760,1235,1760,1235 },  /* 0x20: 1600x1200 for LCDA */
+       { 1, 1,2048,1320,2048,1320 },  /* 0x21: 1600x1200 for non-SiS LVDS */
+       { 1, 1,1664, 861,1664, 861 }   /* 0x22: 1280x854 */
 };
 
 /**************************************************************/
 /* LVDS ----------------------------------------------------- */
 /**************************************************************/
 
-static const SiS_LVDSDataStruct  SiS_LVDS320x480Data_1[]=
+/* FSTN/DSTN 320x240, 2 variants */
+static const struct SiS_LVDSData SiS_LVDS320x240Data_1[]=
 {
        { 848, 433, 400, 525},
        { 848, 389, 400, 525},
@@ -1177,157 +1279,40 @@ static const SiS_LVDSDataStruct  SiS_LVDS320x480Data_1[]=
        { 848, 389, 400, 525},
        { 848, 518, 400, 525},
        {1056, 628, 400, 525},
-       { 400, 525, 400, 525},
-       { 800, 449,1000, 644},
-       { 800, 525,1000, 635}
+       { 400, 525, 400, 525}  /* xSTN */
 };
 
-static const SiS_LVDSDataStruct  SiS_LVDS640x480Data_1[]=
+static const struct SiS_LVDSData SiS_LVDS320x240Data_2[]=
 {
-       { 800, 445, 800, 525},   /* 800, 449, 800, 449 */
+       { 800, 445, 800, 525},
        { 800, 395, 800, 525},
        { 800, 445, 800, 525},
        { 800, 395, 800, 525},
        { 800, 525, 800, 525},
-       { 800, 525, 800, 525},   /* pseudo */
-       { 800, 525, 800, 525}    /* pseudo */
+       {1056, 628,1056, 628},
+       { 480, 525, 480, 525} /* xSTN */
 };
 
-/* FSTN 320x240 */
-static const SiS_LVDSDataStruct  SiS_LVDS640x480Data_2[]=
+static const struct SiS_LVDSData SiS_LVDS640x480Data_1[]=
 {
-       { 800, 445, 800, 525},
+       { 800, 445, 800, 525},   /* 800, 449, 800, 449 */
        { 800, 395, 800, 525},
        { 800, 445, 800, 525},
        { 800, 395, 800, 525},
-       { 800, 525, 800, 525},
-        { 800, 525, 800, 525},   /* pseudo */
-       { 800, 525, 800, 525}    /* pseudo */
+       { 800, 525, 800, 525}
 };
 
-static const SiS_LVDSDataStruct  SiS_LVDS800x600Data_1[]=
+static const struct SiS_LVDSData SiS_LVDS800x600Data_1[]=
 {
        { 848, 433,1060, 629},
        { 848, 389,1060, 629},
        { 848, 433,1060, 629},
        { 848, 389,1060, 629},
        { 848, 518,1060, 629},
-       {1056, 628,1056, 628},
        {1056, 628,1056, 628}
 };
 
-static const SiS_LVDSDataStruct  SiS_LVDS800x600Data_2[]=
-{
-       {1056, 628,1056, 628}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_1[]=
-{
-       { 840, 438,1344, 806},
-       { 840, 409,1344, 806},
-       { 840, 438,1344, 806},
-       { 840, 409,1344, 806},
-       { 840, 518,1344, 806},   /* 640x480 */
-       {1050, 638,1344, 806},   /* 800x600 */
-       {1344, 806,1344, 806},   /* 1024x768 */
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1024x768Data_2[]=
-{
-       {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1280x1024Data_1[]=
-{
-       {1048, 442,1688,1066},
-       {1048, 392,1688,1066},
-       {1048, 442,1688,1066},
-       {1048, 392,1688,1066},
-       {1048, 522,1688,1066},
-       {1208, 642,1688,1066},
-       {1432, 810,1688,1066},
-       {1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1280x1024Data_2[]=
-{
-       {1688,1066,1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1400x1050Data_1[]=
-{
-        { 928, 416, 1688,1066},
-       { 928, 366, 1688,1066},
-       { 928, 416, 1688,1066},
-       { 928, 366, 1688,1066},
-       { 928, 496, 1688,1066},
-       {1088, 616, 1688,1066},
-       {1312, 784, 1688,1066},
-       {1568,1040, 1688,1066},
-       {1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1400x1050Data_2[]=
-{
-        {1688,1066, 1688,1066}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1600x1200Data_1[]=
-{
-       {1088, 520, 2048,1320},
-       {1088, 470, 2048,1320},
-       {1088, 520, 2048,1320},
-       {1088, 470, 2048,1320},
-       {1088, 600, 2048,1320},
-       {1248, 720, 2048,1320},
-       {1472, 888, 2048,1320},
-       {1728,1144, 2048,1320},
-       {1848,1170, 2048,1320},
-       {2048,1320, 2048,1320}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1600x1200Data_2[]=
-{
-        {2048,1320, 2048,1320}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1280x960Data_1[]=
-{
-       { 840, 438,1344, 806},
-       { 840, 409,1344, 806},
-       { 840, 438,1344, 806},
-       { 840, 409,1344, 806},
-       { 840, 518,1344, 806},
-       {1050, 638,1344, 806},
-       {1344, 806,1344, 806},
-       { 800, 449,1280, 801},
-       { 800, 525,1280, 813}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1280x960Data_2[]=
-{
-       {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1280x768Data_1[]=
-{
-       { 768, 438, 1408, 806},
-       { 768, 388, 1408, 806},
-       { 768, 438, 1408, 806},
-       { 768, 388, 1408, 806},
-       { 768, 518, 1408, 806},
-       { 928, 638, 1408, 806},
-       {1152, 806, 1408, 806},
-       {1408, 806, 1408, 806},
-       {1408, 806, 1408, 806}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1280x768Data_2[]=
-{
-       {1408, 806, 1408, 806}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1024x600Data_1[] =
+static const struct SiS_LVDSData SiS_LVDS1024x600Data_1[] =
 {
        { 840, 604,1344, 800},
        { 840, 560,1344, 800},
@@ -1338,124 +1323,18 @@ static const SiS_LVDSDataStruct  SiS_LVDS1024x600Data_1[] =
        {1344, 800,1344, 800}
 };
 
-static const SiS_LVDSDataStruct  SiS_LVDS1024x600Data_2[] =
-{
-       {1344, 800,1344, 800}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_1[] =
+static const struct SiS_LVDSData SiS_LVDS1024x768Data_1[]=
 {
        { 840, 438,1344, 806},
        { 840, 409,1344, 806},
        { 840, 438,1344, 806},
        { 840, 409,1344, 806},
-       { 840, 518,1344, 806},
-       {1050, 638,1344, 806},
-       {1344, 806,1344, 806}
-};
-
-static const SiS_LVDSDataStruct  SiS_LVDS1152x768Data_2[] =
-{
-       {1344, 806,1344, 806}
-};
-
-/* Pass 1:1 data */
-static const SiS_LVDSDataStruct  SiS_LVDSXXXxXXXData_1[]=
-{
-        { 800, 449,  800, 449},
-       { 800, 449,  800, 449},
-       { 900, 449,  900, 449},
-       { 900, 449,  900, 449},
-       { 800, 525,  800, 525},  /*  640x480  */
-       {1056, 628, 1056, 628},  /*  800x600  */
-       {1344, 806, 1344, 806},  /* 1024x768  */
-       {1688,1066, 1688,1066},  /* 1280x1024 */  /* INSERTED */
-       {1688, 806, 1688, 806},  /* 1280x768  */
-};
-
-/* Custom data for Barco iQ R series */
-static const SiS_LVDSDataStruct  SiS_LVDSBARCO1366Data_1[]=
-{
-       { 832, 438,1331, 806},
-       { 832, 388,1331, 806},
-       { 832, 438,1331, 806},
-       { 832, 388,1331, 806},
-       { 832, 518,1331, 806},
-       {1050, 638,1344, 806},
-       {1344, 806,1344, 806},
-       {1688,1066,1688,1066},
-       {1688,1066,1688,1066}   /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ R series */
-static const SiS_LVDSDataStruct  SiS_LVDSBARCO1366Data_2[]=
-{
-       {1344, 806,1344, 806},
-       {1344, 806,1344, 806},
-       {1344, 806,1344, 806},
-       {1344, 806,1344, 806},
-       {1344, 806,1344, 806},
-       {1344, 806,1344, 806},
-       {1344, 806,1344, 806},
-       {1688,1066,1688,1066},
-       {1688,1066,1688,1066}   /* 1360x1024 */
-};
-
-/* Custom data for Barco iQ G series */
-static const SiS_LVDSDataStruct  SiS_LVDSBARCO1024Data_1[]=
-{
-       { 832, 438,1331, 806},
-       { 832, 409,1331, 806},
-       { 832, 438,1331, 806},
-       { 832, 409,1331, 806},
-       { 832, 518,1331, 806},   /* 640x480 */
+       { 840, 518,1344, 806},   /* 640x480 */
        {1050, 638,1344, 806},   /* 800x600 */
        {1344, 806,1344, 806},   /* 1024x768 */
 };
 
-/* Custom data for Barco iQ G series */
-static const SiS_LVDSDataStruct  SiS_LVDSBARCO1024Data_2[]=
-{
-       {1344, 806,1344, 806}
-};
-
-/* Custom data for 848x480 parallel panel */
-static const SiS_LVDSDataStruct  SiS_LVDS848x480Data_1[]=
-{
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {1088, 525,1088, 525},  /* 640x480 TODO */
-       {1088, 525,1088, 525},  /* 800x600 TODO */
-       {1088, 525,1088, 525},  /* 1024x768 TODO */
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {1088, 525,1088, 525},  /* 848x480 */
-       {1088, 525,1088, 525}   /* 1360x768 TODO */
-};
-
-/* Custom data for 848x480 parallel panel */
-static const SiS_LVDSDataStruct  SiS_LVDS848x480Data_2[]=
-{
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {1088, 525,1088, 525},  /*  640x480 */
-       {1088, 525,1088, 525},  /*  800x600 */
-       {1088, 525,1088, 525},  /* 1024x768 */
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {   0,   0,   0,   0},
-       {1088, 525,1088, 525},  /* 848x480 */
-       {1088, 525,1088, 525}   /* 1360x768 TODO */
-};
-
-static const SiS_LVDSDataStruct  SiS_CHTVUNTSCData[]=
+static const struct SiS_LVDSData SiS_CHTVUNTSCData[]=
 {
        { 840, 600, 840, 600},
        { 840, 600, 840, 600},
@@ -1466,7 +1345,7 @@ static const SiS_LVDSDataStruct  SiS_CHTVUNTSCData[]=
         {1160, 945,1160, 945}
 };
 
-static const SiS_LVDSDataStruct  SiS_CHTVONTSCData[]=
+static const struct SiS_LVDSData SiS_CHTVONTSCData[]=
 {
        { 840, 525, 840, 525},
        { 840, 525, 840, 525},
@@ -1477,55 +1356,9 @@ static const SiS_LVDSDataStruct  SiS_CHTVONTSCData[]=
         {1160, 840,1160, 840}
 };
 
-/* Chrontel TV Skew */
-
-static const SiS_LVDSDesStruct  SiS_CHTVUNTSCDesData[]=
-{
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS_CHTVONTSCDesData[]=
-{
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS_CHTVUPALDesData[]=
-{
-       {256,  0},
-       {256,  0},
-       {256,  0},
-       {256,  0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
-static const SiS_LVDSDesStruct  SiS_CHTVOPALDesData[]=
-{
-       {256,  0},
-       {256,  0},
-       {256,  0},
-       {256,  0},
-       { 0,   0},
-       { 0,   0},
-       { 0,   0}
-};
-
 /* CRT1 CRTC data for slave modes */
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1320x480_1[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_1[] =
 {
  {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1550,48 +1383,7 @@ static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1320x480_1[] =
    0x00 }}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_1[] =
-{
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
-   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
-   0x00}},
- {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
-   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_1_H[] =
-{
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
-   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
-   0x00}},
- {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
-   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
-   0x00}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_2[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2[] =
 {
  {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
    0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
@@ -1611,12 +1403,17 @@ static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_2[] =
  {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
    0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
    0x01}},
+#if 0
  {{0x2d,0x27,0x90,0x2c,0x80,0x0b,0x3e,
    0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
    0x00}}
+#endif
+ {{0x5f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xe8,0x0c,0x00,0x00,0x05,
+   0x00}},
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_2_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_2_H[] =
 {
  {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1641,7 +1438,7 @@ static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_2_H[] =
    0x00}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_3[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3[] =
 {
  {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
    0xe9,0x8b,0xdf,0x04,0x00,0x00,0x05,
@@ -1666,7 +1463,7 @@ static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_3[] =
    0x00}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_3_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1320x240_3_H[] =
 {
  {{0x65,0x4f,0x89,0x56,0x83,0xaa,0x1f,
    0x90,0x85,0x8f,0xab,0x30,0x00,0x05,
@@ -1691,778 +1488,175 @@ static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT1640x480_3_H[] =
    0x00}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11024x600_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
-   0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
-   0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x5a,0x3e,
-   0xe8,0x8f,0x8f,0x5b,0x00,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x2e,0x3e,
-   0xb9,0x80,0x5d,0x2f,0x00,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xaf,0xba,
-   0x3b,0x82,0xdf,0xb0,0x00,0x00,0x01,
-   0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x1e,0xf1,
-   0xae,0x85,0x57,0x1f,0x30,0x00,0x26,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x1e,0xf1,
-   0xae,0x85,0x57,0x1f,0x30,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11024x600_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
-   0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
-   0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
-   0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
-   0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11024x600_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11024x600_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
-   0xae,0x84,0x57,0x25,0x30,0x00,0x01,
-   0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11152x768_1[] =
-{
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x97,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x01,
-   0x00}},
- {{0x64,0x4f,0x88,0x54,0x9f,0x04,0x3e,
-   0xe2,0x89,0xdf,0x05,0x00,0x00,0x01,
-   0x00}},
- {{0x7e,0x63,0x82,0x68,0x15,0x7c,0xf0,
-   0x5a,0x8f,0x57,0x7d,0x20,0x00,0x26,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11152x768_1_H[] =
-{
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0xc4,0x1f,
-   0x92,0x89,0x8f,0xb5,0x30,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x97,0x1f,
-   0x60,0x87,0x5d,0x83,0x10,0x00,0x44,
-   0x00}},
- {{0x2f,0x27,0x93,0x2b,0x90,0x04,0x3e,
-   0xe2,0x89,0xdf,0x05,0x00,0x00,0x44,
-   0x00}},
- {{0x3c,0x31,0x80,0x35,0x1c,0x7c,0xf0,
-   0x5a,0x8f,0x57,0x7d,0x20,0x00,0x55,
-   0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11152x768_2[] =
-{
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x4f,0x87,0x6e,0x9f,0x24,0xbb,
-   0x72,0x88,0xdf,0x25,0x30,0x00,0x06,
-   0x00}},
- {{0xa3,0x63,0x87,0x78,0x89,0x24,0xf1,
-   0xae,0x84,0x57,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xa3,0x7f,0x87,0x86,0x97,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x02,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11152x768_2_H[] =
-{
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x4a,0x80,0x8f,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x31,0x87,0x5d,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x27,0x93,0x39,0x01,0x24,0xbb,
-   0x72,0x88,0xdf,0x25,0x30,0x00,0x01,
-   0x00}},
- {{0x4f,0x31,0x93,0x3e,0x06,0x24,0xf1,
-   0xae,0x84,0x57,0x25,0x30,0x00,0x01,
-   0x01}},
- {{0x4f,0x3f,0x93,0x45,0x0d,0x24,0xf5,
-   0x02,0x88,0xff,0x25,0x10,0x00,0x01,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11280x768_1[] =
-{
- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
-   0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
-   0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
-   0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
-   0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0xb4,0x1f,
-   0x9c,0x8e,0x8f,0xb5,0x10,0x00,0x01,
-   0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x82,0x1f,
-   0x6a,0x8c,0x5d,0x83,0x30,0x00,0x01,
-   0x00}},
- {{0x5b,0x4f,0x9f,0x55,0x19,0x04,0x3e,
-   0xec,0x8e,0xdf,0x05,0x20,0x00,0x01,
-   0x00}},
- {{0x6f,0x63,0x93,0x69,0x8d,0x7c,0xf0,
-   0x64,0x86,0x57,0x7d,0x20,0x00,0x05,
-   0x01}},
- {{0x8b,0x7f,0x8f,0x85,0x09,0x24,0xf5,
-   0x0c,0x8e,0xff,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
-   0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
-   0x01}},
- {{0xab,0x9f,0x8f,0xa5,0x89,0x24,0xf5,
-   0x0c,0x8e,0xff,0x25,0x30,0x00,0x06,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11280x768_1_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1[] =
 {
- {{0x47,0x27,0x8b,0x2c,0x1a,0x9e,0x1f,
-   0x93,0x86,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x30,0x1e,0x9e,0x1f,
-   0x92,0x86,0x8f,0x9f,0x30,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0x6c,0x1f,
-   0x60,0x84,0x5d,0x6d,0x10,0x00,0x05,
-   0x00}},
- {{0x47,0x27,0x8b,0x2c,0x1a,0xee,0x1f,
-   0xe2,0x86,0xdf,0xef,0x10,0x00,0x05,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
    0x00}},
- {{0x51,0x31,0x95,0x36,0x04,0x66,0xf0,
-   0x5a,0x8e,0x57,0x67,0x20,0x00,0x01,
-   0x01}},
- {{0x5f,0x3f,0x83,0x44,0x92,0x0e,0xf5,
-   0x02,0x86,0xff,0x0f,0x10,0x00,0x01,
-   0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-   0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
-   0x01}},
- {{0x6f,0x4f,0x93,0x54,0x82,0x0e,0x5a,
-   0x02,0x86,0xff,0x0f,0x09,0x00,0x05,
-   0x01}}
-};
-
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11280x768_2[] =
-{
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
-   0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
    0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
-   0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
    0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
-   0x54,0x86,0xdb,0xda,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
    0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xbb,
-   0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x02,
+ {{0x5f,0x4f,0x82,0x55,0x81,0x0b,0x3e,
+   0xe9,0x8b,0xdf,0x04,0x30,0x00,0x05,
    0x00}},
- {{0xab,0x60,0x9f,0x80,0x04,0x24,0xb3,
-   0x7c,0x8e,0x03,0x02,0x10,0x00,0x02,
-   0x01}},
- {{0xab,0x63,0x8f,0x8a,0x8e,0x24,0xf1,
-   0xb6,0x88,0x57,0x25,0x10,0x00,0x02,
-   0x01}},
- {{0xab,0x7f,0x8f,0x98,0x9c,0x24,0xf5,
-   0x0a,0x8c,0xff,0x25,0x30,0x00,0x02,
-   0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
-   0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
-   0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
-   0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
+ {{0x7f,0x63,0x83,0x6c,0x1c,0x72,0xf0,
+   0x58,0x8c,0x57,0x73,0x20,0x00,0x06,
    0x01}}
 };
 
-static const SiS_LVDSCRT1DataStruct  SiS_LVDSCRT11280x768_2_H[] =
+static const struct SiS_LVDSCRT1Data SiS_LVDSCRT1640x480_1_H[] =
 {
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
-   0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
    0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
-   0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
    0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
-   0x54,0x86,0xdb,0xda,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x9c,0x8e,0x96,0xb9,0x00,0x00,0x00,
    0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xbb,
-   0x3b,0x8d,0xc2,0xc1,0x00,0x00,0x01,
+ {{0x2d,0x28,0x90,0x2b,0xa0,0xbf,0x1f,
+   0x83,0x85,0x63,0xba,0x00,0x00,0x00,
    0x00}},
- {{0x83,0x38,0x97,0x58,0x9c,0x24,0xb3,
-   0x7c,0x8e,0x03,0x02,0x10,0x00,0x01,
-   0x01}},
- {{0x79,0x31,0x9d,0x58,0x9c,0x24,0xf1,
-   0xb6,0x88,0x57,0x25,0x10,0x00,0x01,
-   0x01}},
- {{0x6b,0x3f,0x8f,0x58,0x9c,0x24,0xf5,
-   0x0a,0x8c,0xff,0x25,0x30,0x00,0x01,
-   0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
-   0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
-   0x01}},
- {{0xab,0x9f,0x8f,0xa8,0x8c,0x24,0xf5,
-   0x0a,0x8c,0xff,0x25,0x30,0x00,0x06,
-   0x01}}
-};
-
-/**************************************************************/
-/* COMMON --------------------------------------------------- */
-/**************************************************************/
-
-#ifdef LINUX_XF86
-
-#define SIS_PL_HSYNCP 0x01
-#define SIS_PL_HSYNCN 0x02
-#define SIS_PL_VSYNCP 0x04
-#define SIS_PL_VSYNCN 0x08
-#define SIS_PL_DVI    0x80
-
-typedef struct _SiS_PlasmaModes
-{
-  const char *name;
-  ULONG  clock;
-  USHORT HDisplay, HTotal, HFrontPorch, HSyncWidth;
-  USHORT VDisplay, VTotal, VFrontPorch, VSyncWidth;
-  UCHAR  SyncFlags;
-} SiS_PlasmaModes;
-
-typedef struct _SiS_PlasmaTables
-{
-   USHORT vendor;
-   UCHAR  productnum;
-   USHORT product[5];
-   const char *DDCnames[5];
-   const char *plasmaname;
-   USHORT maxx,maxy;
-   USHORT prefx, prefy;
-   UCHAR  modenum;
-   UCHAR  plasmamodes[20];  /* | 0x80 = DVI-capable, | 0x40 = analog */
-} SiS_PlasmaTables;
-
-static const SiS_PlasmaModes SiS_PlasmaMode[] = {
-   {  "640x400",               /* 00: IBM 400@70 */
-      25175,
-       640,  800, 17,  64,
-       400,  449, 13,   2,
-      SIS_PL_HSYNCN | SIS_PL_VSYNCN },
-   {  "640x480",               /* 01: VESA 480@72 */
-      31500,
-       640,  832, 24,  40,
-       480,  520,  9,   3,
-      SIS_PL_HSYNCN | SIS_PL_VSYNCN },
-   {  "800x600",               /* 02: VESA 600@72 */
-      50000,
-       800, 1040, 56, 120,
-       600,  666, 37,   6,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "864x480",               /* 03: Cereb wide 1 */
-      42526,
-       864, 1134, 22,  86,
-       480,  500,  1,   3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCN },
-   {  "848x480",               /* 04: VESA wide (NEC1) */
-      33750,
-       848, 1088, 16, 112,
-       480,  517,  6,   8,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1024x576",              /* 05: VESA wide (NEC2) */
-      47250,
-      1024, 1320, 16, 144,
-       576,  596,  2,   4,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1280x720",              /* 06: VESA wide (NEC3) */
-      76500,
-      1280, 1696, 48, 176,
-       720,  750,  4,   8,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1360x765",              /* 07: VESA wide (NEC4) */
-      85500,
-      1360, 1792, 64, 176,
-       765,  795,  4,   8,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1024x600",              /* 08: CEREB wide 2 */
-      51200,
-      1024, 1352, 51, 164,
-       600,  628,  1,   4,
-      SIS_PL_HSYNCN | SIS_PL_VSYNCP },
-   {  "1024x768",              /* 09: VESA 768@75 */
-      78750,
-      1024, 1312,  16, 96,
-       768,  800,   1,  3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1152x864",              /* 10: VESA 1152x864@75 */
-      108000,
-      1152, 1600, 64, 128,
-       864,  900,  1,   3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1280x1024",             /* 11: VESA 1024@60 */
-      108000,
-      1280, 1688, 48, 112,
-      1024, 1066,  1,   3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1280x768",              /* 12: W_XGA */
-      81000,
-      1280, 1688, 48, 112,
-       768,  802,  3,   6,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCN },
-   {  "1280x768",              /* 13: I/O Data W_XGA@56Hz */
-      76064,
-      1280, 1688, 48, 112,
-       768,  802,  2,   3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1376x768",              /* 14: I/O Wide XGA */
-      87340,
-      1376, 1808, 32, 128,
-       768,  806,  3,   6,
-      SIS_PL_HSYNCN | SIS_PL_VSYNCP },
-   {  "1280x960",              /* 15: VESA 960@60 */
-      108000,
-      1280, 1800, 96, 112,
-       960, 1000,  1,   3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1400x1050",             /* 16: VESA 1050@60Hz */
-      108000,
-      1400, 1688, 48, 112,
-      1050, 1066,  1,   3,
-      SIS_PL_HSYNCN | SIS_PL_VSYNCN },
-   {  "1360x768",              /* 17: VESA wide (NEC4/2) */
-      85500,
-      1360, 1792, 64, 112,
-       765,  795,  3,   6,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "800x600",               /* 18: VESA 600@56 */
-      36000,
-       800, 1024, 24,   2,
-       600,  625,  1,   2,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1072x600",              /* 19: Panasonic 1072x600 (sync?) */
-      54100,
-       1072, 1424, 48, 176,
-        600,  628, 16,   1,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "848x480",               /* 20: Panasonic 848x480 (sync?) */
-      33070,                   /* is 852x480, but we can't use 852 */
-        848, 1068, 20,  40,    /* differs from DDC data, better centered */
-        480,  516,  3,   5,    /* won't work assumingly, because data is % 8 */
-      SIS_PL_HSYNCN | SIS_PL_VSYNCN },
-   {  "1280x720",              /* 21: WIDE720(60) (aka "750p") (Panasonic) */
-      74300,
-      1280, 1650,110,  40,
-       720,  750,  5,   5,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1280x768",              /* 22: 1280x768@56.5 (Panasonic) */
-      76200,                   /* (According to manual not supported for HDMI; but works) */
-      1280, 1680, 16,  24,
-       768,  802,  2,   5,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1280x720@50",           /* 23: WIDE720(50) (aka "750p") (Panasonic) */
-      74300,                   /* Panasonic states 45.0kHz. Not possible. This one works (with some overscan) */
-      1280, 1980,400,  80,
-       720,  750,  1,   2,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "720x480",               /* 24: 720x480 (aka "525p" and "480p") (Panasonic) */
-      27000,
-       720,  856, 40,  32,
-       480,  525,  1,   3,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "720x576",               /* 25: 720x576 (aka "625p"and "576p") (Panasonic) */
-      27500,
-       720,  864, 16,  64,
-       576,  625,  5,   6,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
-   {  "1280x720@50",           /* 26: WIDE720(50) (aka "750p") (Generic) */
-      74300,
-      1280, 1980,400,  80,
-       720,  750,  5,   5,
-      SIS_PL_HSYNCP | SIS_PL_VSYNCP },
+ {{0x2d,0x28,0x90,0x2c,0x80,0x0b,0x3e,
+   0xe9,0x8b,0xe7,0x04,0x00,0x00,0x00,
+   0x00}}
 };
 
-/*
-27.00  720 755 791 858  480 480 484 525
-27.50  720 732 795 864  576 581 587 625
-*/
-
-static const SiS_PlasmaTables SiS_PlasmaTable[] = {
-#if 0  /* Product IDs missing */
-   { 0x38a3, 4,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 42VP4/42VP4D/42VP4G/42VP4DG",
-     0, 0,
-     0, 0,
-     11,   /* All DVI, except 0, 7, 13 */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
-      17|0xc0, 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
+BOOLEAN                SiSInitPtr(struct SiS_Private *SiS_Pr);
+#ifdef SIS_XORG_XF86
+unsigned short SiS_GetModeID(int VGAEngine, unsigned int VBFlags, int HDisplay, int VDisplay,
+                               int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
 #endif
-#if 0  /* Product IDs missing */
-   { 0x38a3, 3,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 42PD1/50PD1/50PD2",
-     0, 0,
-     0, 0,
-     5,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0, 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 1,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 42PD3",
-     0, 0,
-     0, 0,
-     10,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 7|0x40, 8|0xc0, 9|0xc0,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 2,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 42VM3/61XM1",
-     0, 0,
-     0, 0,
-     11,  /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 3|0xc0, 4|0xc0, 5|0xc0, 6|0xc0, 8|0xc0, 9|0xc0,11|0xc0,
-      17|0xc0, 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 2,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 42MP1/42MP2",
-     0, 0,
-     0, 0,
-     6,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 1,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 50MP1",
-     0, 0,
-     0, 0,
-     10,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
+unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+                               int VDisplay, int Depth, BOOLEAN FSTN,
+                               unsigned short CustomT, int LCDwith, int LCDheight,
+                               unsigned int VBFlags2);
+unsigned short SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+                               int VDisplay, int Depth, unsigned int VBFlags2);
+unsigned short SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+                               int VDisplay, int Depth, unsigned int VBFlags2);
+
+void           SiS_SetReg(SISIOADDRESS port, unsigned short index, unsigned short data);
+void           SiS_SetRegByte(SISIOADDRESS port, unsigned short data);
+void           SiS_SetRegShort(SISIOADDRESS port, unsigned short data);
+void           SiS_SetRegLong(SISIOADDRESS port, unsigned int data);
+unsigned char  SiS_GetReg(SISIOADDRESS port, unsigned short index);
+unsigned char  SiS_GetRegByte(SISIOADDRESS port);
+unsigned short SiS_GetRegShort(SISIOADDRESS port);
+unsigned int   SiS_GetRegLong(SISIOADDRESS port);
+void           SiS_SetRegANDOR(SISIOADDRESS Port, unsigned short Index, unsigned short DataAND,
+                               unsigned short DataOR);
+void           SiS_SetRegAND(SISIOADDRESS Port,unsigned short Index, unsigned short DataAND);
+void           SiS_SetRegOR(SISIOADDRESS Port,unsigned short Index, unsigned short DataOR);
+
+void           SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+void           SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+void           SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+#ifndef SIS_LINUX_KERNEL
+void           SiSSetLVDSetc(struct SiS_Private *SiS_Pr);
 #endif
-   { 0x38a3, 4,
-     { 0xa482, 0xa483, 0x0000, 0x0000, 0x0000 },
-     { "PX-42VM", "", "", "", "" },
-     "NEC PlasmaSync 42MP3/42MP4/50MP2/61MP1",
-     0, 0,
-     0, 0,
-     11,   /* All DVI except 0, 7, 13, 17 */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,10|0xc0,11|0xc0,13|0x40,14|0xc0,
-      17|0x40, 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-#if 0  /* Product IDs missing */
-   { 0x38a3, 1,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 3300W",
-     0, 0,
-     0, 0,
-     3,
-     { 0|0x40, 1|0xc0,18|0xc0, 0     , 0     , 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 1,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 4200W",
-     4,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 0     , 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 1,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 4210W",
-     0, 0,
-     0, 0,
-     6,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 9|0xc0,11|0xc0, 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x38a3, 1,
-     { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "NEC PlasmaSync 5000W",
-     0, 0,
-     0, 0,
-     7,   /* DVI entirely unknown */
-     { 0|0x40, 1|0xc0, 2|0xc0, 4|0xc0, 7|0x40, 9|0xc0,11|0xc0, 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-#endif
-   { 0x412f, 2,
-     { 0x000c, 0x000b, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "Pioneer 503CMX/PDA-5002",
-     0, 0,
-     0, 0,
-     6,   /* DVI unknown */
-     { 1|0xc0, 2|0xc0, 9|0xc0,11|0xc0,12|0xc0,15|0xc0, 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x34a9, 1,
-     { 0xa00e, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "", "", "", "", "" },
-     "Panasonic TH-42",
-     0, 0,
-     0, 0,
-     5,   /* No DVI output */
-     { 1|0x40, 2|0x40, 4|0x40, 9|0x40,15|0x40, 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x34a9, 1,
-     { 0xa005, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "TH-42PW*4", "", "", "", "" },
-     "Panasonic TH-42PW5",
-     0, 0,
-     0, 0,
-     1,   /* No special modes otherwise; no DVI. */
-     {20|0x40,19|0x40, 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x4c2e, 1,
-     { 0x9b05, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "PLV-Z2", "", "", "", "" },
-     "Sanyo PLV-Z2 (non HDCP-mode)",   /* HDCP mode would be id 9b06, but not needed */
-     1280, 768,                                /* as it then advertises correct size */
-     1280, 720,
-     1,   /* 1280x720, no special modes otherwise */
-     {21|0xc0, 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x34a9, 1,
-     { 0xd034, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "AE500U (DVI-D)", "", "", "", "" },
-     "Panasonic AE500U",
-     1280, 768,
-     1280, 720,
-     1,   /* 1280x720, no special modes otherwise */
-     {21|0xc0, 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x34a9, 1,
-     { 0xd043, 0x0000, 0x0000, 0x0000, 0x0000 },
-     { "AE700U (HDMI)", "", "", "", "" },
-     "Panasonic AE700U",
-     1360, 768,
-     1280, 720,
-     6,   /* 1280x720/60, 1280x720/50, 1280x768@56(digital/analog), 720x480, 720x576 */
-     {21|0xc0,23|0xc0,22|0x80,13|0x40,24|0x80,25|0x80, 0     , 0     , 0     , 0     ,
-       0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0     , 0       }
-   },
-   { 0x0000 }
-};
+void           SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+void           SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+unsigned short SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+BOOLEAN                SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void           SiS_GetVBType(struct SiS_Private *SiS_Pr);
 #endif
 
-#ifdef LINUX_XF86
-USHORT  SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay,
-                         int Depth, BOOLEAN FSTN, int LCDwith, int LCDheight);
+BOOLEAN                SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+                               unsigned short *ModeIdIndex);
+unsigned short SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+unsigned short  SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short  SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+unsigned short SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+unsigned short SiS_GetOffset(struct SiS_Private *SiS_Pr,unsigned short ModeNo,
+                               unsigned short ModeIdIndex, unsigned short RRTI);
+#ifdef SIS300
+void           SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *idx1,
+                               unsigned short *idx2);
+unsigned short SiS_GetFIFOThresholdB300(unsigned short idx1, unsigned short idx2);
+unsigned short SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
 #endif
-USHORT  SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN,
-                          USHORT CustomT, int LCDwith, int LCDheight);
-USHORT  SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-USHORT  SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-
-void   SiS_SetReg(SISIOADDRESS port, USHORT index, USHORT data);
-void   SiS_SetRegByte(SISIOADDRESS port, USHORT data);
-void   SiS_SetRegShort(SISIOADDRESS port, USHORT data);
-void   SiS_SetRegLong(SISIOADDRESS port, ULONG data);
-UCHAR  SiS_GetReg(SISIOADDRESS port, USHORT index);
-UCHAR  SiS_GetRegByte(SISIOADDRESS port);
-USHORT SiS_GetRegShort(SISIOADDRESS port);
-ULONG  SiS_GetRegLong(SISIOADDRESS port);
-void   SiS_SetRegANDOR(SISIOADDRESS Port, USHORT Index, USHORT DataAND, USHORT DataOR);
-void   SiS_SetRegAND(SISIOADDRESS Port,USHORT Index, USHORT DataAND);
-void   SiS_SetRegOR(SISIOADDRESS Port,USHORT Index, USHORT DataOR);
-void   SiS_DisplayOn(SiS_Private *SiS_Pr);
-void   SiS_DisplayOff(SiS_Private *SiS_Pr);
-void   SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void   SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
-void   SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-BOOLEAN        SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex);
-UCHAR  SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-USHORT SiS_GetOffset(SiS_Private *SiS_Pr,USHORT ModeNo, USHORT ModeIdIndex,
-              USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-void   SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT ModeIdIndex);
-void   SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-
-#ifdef LINUX_XF86
-BOOLEAN        SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,ScrnInfoPtr pScrn,USHORT ModeNo, BOOLEAN dosetpitch);
-BOOLEAN        SiSBIOSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN        SiSBIOSSetModeCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom);
-BOOLEAN        SiSBIOSSetModeCRT1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, ScrnInfoPtr pScrn,
-               DisplayModePtr mode, BOOLEAN IsCustom);
-int    SiSTranslateToVESA(ScrnInfoPtr pScrn, int modenumber);
-int    SiSTranslateToOldMode(int modenumber);
-BOOLEAN        SiS_GetPanelID(SiS_Private *SiS_Pr, PSIS_HW_INFO);
-USHORT         SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode, int VBFlags);
-DisplayModePtr SiSBuildBuiltInModeList(ScrnInfoPtr pScrn, BOOLEAN includelcdmodes, BOOLEAN isfordvi);
-int    SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct, int *maxx, int *maxy, int *prefx, int *prefy);
-void    SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c);
-#else
-BOOLEAN        SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,USHORT ModeNo);
+void           SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+#ifdef SIS_XORG_XF86
+BOOLEAN                SiSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn, unsigned short ModeNo,
+                               BOOLEAN dosetpitch);
+BOOLEAN                SiSBIOSSetMode(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+                               DisplayModePtr mode, BOOLEAN IsCustom);
+BOOLEAN                SiSBIOSSetModeCRT2(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+                               DisplayModePtr mode, BOOLEAN IsCustom);
+BOOLEAN                SiSBIOSSetModeCRT1(struct SiS_Private *SiS_Pr, ScrnInfoPtr pScrn,
+                               DisplayModePtr mode, BOOLEAN IsCustom);
+#endif
+#ifdef SIS_LINUX_KERNEL
+BOOLEAN                SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+#endif
+void           SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+void           SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+#ifdef SIS_XORG_XF86
+void           SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+                               int yres, DisplayModePtr current);
+#endif
+#ifdef SIS_LINUX_KERNEL
+void           SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+                               int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
 #endif
 
-#ifdef LINUX_KERNEL
-int            sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                             UCHAR modeno, UCHAR rateindex);
-int            sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                       UCHAR modeno, UCHAR rateindex,
-                       struct fb_var_screeninfo *var);
-BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                       UCHAR modeno, int *htotal, int *vtotal, UCHAR rateindex);
+/* From init301.c: */
+extern void            SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex, int chkcrt2mode);
+extern void            SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern void            SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+extern void            SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern void            SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+extern void            SiS_DisableBridge(struct SiS_Private *);
+extern BOOLEAN         SiS_SetCRT2Group(struct SiS_Private *, unsigned short);
+extern unsigned short  SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern void            SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+extern unsigned short  SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern unsigned short  SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+extern unsigned short  SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex, unsigned short RRTI);
+extern BOOLEAN         SiS_IsVAMode(struct SiS_Private *);
+extern BOOLEAN         SiS_IsDualEdge(struct SiS_Private *);
+
+#ifdef SIS_XORG_XF86
+/* From other modules: */
+extern unsigned short  SiS_CheckBuildCustomMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
+                               unsigned int VBFlags);
+extern unsigned char   SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, unsigned short offset,
+                               unsigned char value);
+extern unsigned char   SiS_GetSetModeID(ScrnInfoPtr pScrn, unsigned char id);
+extern unsigned short  SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
+                               unsigned int VBFlags);
 #endif
 
-/* init301.c: */
-extern void     SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                               PSIS_HW_INFO HwInfo, int chkcrt2mode);
-extern void     SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                               PSIS_HW_INFO HwInfo);
-extern void     SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void    SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-extern void     SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-extern void     SiS_DisableBridge(SiS_Private *, PSIS_HW_INFO);
-extern BOOLEAN  SiS_SetCRT2Group(SiS_Private *, PSIS_HW_INFO, USHORT);
-extern USHORT   SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                                       PSIS_HW_INFO HwInfo);
-extern void     SiS_WaitRetrace1(SiS_Private *SiS_Pr);
-extern USHORT   SiS_GetResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT   SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-extern USHORT   SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                                       USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-extern BOOLEAN  SiS_IsVAMode(SiS_Private *, PSIS_HW_INFO);
-extern BOOLEAN  SiS_IsDualEdge(SiS_Private *, PSIS_HW_INFO);
-
-#ifdef LINUX_XF86
-/* From other sis driver modules: */
-extern int      SiS_compute_vclk(int Clock, int *out_n, int *out_dn, int *out_div,
-                               int *out_sbit, int *out_scale);
-extern void    SiSCalcClock(ScrnInfoPtr pScrn, int clock, int max_VLD, unsigned int *vclk);
-
-extern UCHAR           SiS_GetSetBIOSScratch(ScrnInfoPtr pScrn, USHORT offset, UCHAR value);
-extern UCHAR           SiS_GetSetModeID(ScrnInfoPtr pScrn, UCHAR id);
-extern USHORT  SiS_GetModeNumber(ScrnInfoPtr pScrn, DisplayModePtr mode, ULONG VBFlags);
+#ifdef SIS_LINUX_KERNEL
+#ifdef SIS300
+extern unsigned int    sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern void            sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg,
+                               unsigned int val);
+#endif
+#ifdef SIS315H
+extern void            sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg,
+                               unsigned char val);
+extern unsigned int    sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
 #endif
 
 #endif
index 274dacd54bb82d269f982333ad1c2bdf79e1d5fc..2d88f908170aad459568e84c2e89d29ca87bcbff 100644 (file)
@@ -2,11 +2,12 @@
 /* $XdotOrg$ */
 /*
  * Mode initializing code (CRT2 section)
- * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
+ * for SiS 300/305/540/630/730,
+ *     SiS 315/550/[M]650/651/[M]661[FGM]X/[M]74x[GX]/330/[M]76x[GX],
+ *     XGI V3XT/V5/V8, Z7
+ * (Universal module for Linux kernel framebuffer and X.org/XFree86 4.x)
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
@@ -38,7 +39,7 @@
  * * 3) The name of the author may not be used to endorse or promote products
  * *    derived from this software without specific prior written permission.
  * *
- * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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,
  * Formerly based on non-functional code-fragements for 300 series by SiS, Inc.
  * Used by permission.
  *
- * TW says: This code looks awful, I know. But please don't do anything about
- * this otherwise debugging will be hell.
- * The code is extremely fragile as regards the different chipsets, different
- * video bridges and combinations thereof. If anything is changed, extreme
- * care has to be taken that that change doesn't break it for other chipsets,
- * bridges or combinations thereof.
- * All comments in this file are by me, regardless if marked TW or not.
- *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #if 1
 #define SET_EMI                /* 302LV/ELV: Set EMI values */
 #endif
 
+#if 1
+#define SET_PWD                /* 301/302LV: Set PWD */
+#endif
+
 #define COMPAL_HACK    /* Needed for Compal 1400x1050 (EMI) */
 #define COMPAQ_HACK    /* Needed for Inventec/Compaq 1280x1024 (EMI) */
 #define ASUS_HACK      /* Needed for Asus A2H 1024x768 (EMI) */
 #define SiS_I2CDELAY      1000
 #define SiS_I2CDELAYSHORT  150
 
-static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr);
-static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx);
+static unsigned short  SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr);
+#ifdef SIS_LINUX_KERNEL
+static void            SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+#endif
 
 /*********************************************/
 /*         HELPER: Lock/Unlock CRT2          */
 /*********************************************/
 
 void
-SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_UnLockCRT2(struct SiS_Private *SiS_Pr)
 {
-   if(HwInfo->jChipType >= SIS_315H)
+   if(SiS_Pr->ChipType == XGI_20)
+      return;
+   else if(SiS_Pr->ChipType >= SIS_315H)
       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2f,0x01);
    else
       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01);
 }
 
-static void
-SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_LockCRT2(struct SiS_Private *SiS_Pr)
 {
-   if(HwInfo->jChipType >= SIS_315H)
+   if(SiS_Pr->ChipType == XGI_20)
+      return;
+   else if(SiS_Pr->ChipType >= SIS_315H)
       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2F,0xFE);
    else
       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x24,0xFE);
@@ -115,9 +125,9 @@ SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static void
-SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
+SiS_SetRegSR11ANDOR(struct SiS_Private *SiS_Pr, unsigned short DataAND, unsigned short DataOR)
 {
-   if(HwInfo->jChipType >= SIS_661) {
+   if(SiS_Pr->ChipType >= SIS_661) {
       DataAND &= 0x0f;
       DataOR  &= 0x0f;
    }
@@ -129,12 +139,12 @@ SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, US
 /*********************************************/
 
 #ifdef SIS315H
-static UCHAR *
-GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned char *
+GetLCDStructPtr661(struct SiS_Private *SiS_Pr)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-   UCHAR  *myptr = NULL;
-   USHORT romindex = 0, reg = 0, idx = 0;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned char  *myptr = NULL;
+   unsigned short romindex = 0, reg = 0, idx = 0;
 
    /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
     * due to the variaty of panels the BIOS doesn't know about.
@@ -144,15 +154,15 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
     */
 
    if((SiS_Pr->SiS_ROMNew) &&
-      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
+      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
 
-      if(HwInfo->jChipType < SIS_661) reg = 0x3c;
-      else                            reg = 0x7d;
+      if(SiS_Pr->ChipType < SIS_661) reg = 0x3c;
+      else                           reg = 0x7d;
 
       idx = (SiS_GetReg(SiS_Pr->SiS_P3d4,reg) & 0x1f) * 26;
 
       if(idx < (8*26)) {
-         myptr = (UCHAR *)&SiS_LCDStruct661[idx];
+         myptr = (unsigned char *)&SiS_LCDStruct661[idx];
       }
       romindex = SISGETROMW(0x100);
       if(romindex) {
@@ -163,11 +173,11 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
    return myptr;
 }
 
-static USHORT
-GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDStructPtr661_2(struct SiS_Private *SiS_Pr)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-   USHORT romptr = 0;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short romptr = 0;
 
    /* Use the BIOS tables only for LVDS panels; TMDS is unreliable
     * due to the variaty of panels the BIOS doesn't know about.
@@ -177,12 +187,12 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
     */
 
    if((SiS_Pr->SiS_ROMNew) &&
-      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) || (!SiS_Pr->PanelSelfDetected))) {
+      ((SiS_Pr->SiS_VBType & VB_SISLVDS) || (!SiS_Pr->PanelSelfDetected))) {
       romptr = SISGETROMW(0x102);
       romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
    }
 
-   return(romptr);
+   return romptr;
 }
 #endif
 
@@ -191,186 +201,187 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static BOOLEAN
-SiS_AdjustCRT2Rate(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   USHORT RRTI, USHORT *i, PSIS_HW_INFO HwInfo)
+SiS_AdjustCRT2Rate(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RRTI, unsigned short *i)
 {
-  USHORT checkmask=0,modeid,infoflag;
+   unsigned short checkmask=0, modeid, infoflag;
 
-  modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
+   modeid = SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID;
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 
-       checkmask |= SupportRAMDAC2;
-       if(HwInfo->jChipType >= SIS_315H) {
-          checkmask |= SupportRAMDAC2_135;
-          if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-             checkmask |= SupportRAMDAC2_162;
-             if(SiS_Pr->SiS_VBType & VB_SIS301C) {
-                checkmask |= SupportRAMDAC2_202;
-             }
-          }
-       }
+        checkmask |= SupportRAMDAC2;
+        if(SiS_Pr->ChipType >= SIS_315H) {
+           checkmask |= SupportRAMDAC2_135;
+           if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+              checkmask |= SupportRAMDAC2_162;
+              if(SiS_Pr->SiS_VBType & VB_SISRAMDAC202) {
+                 checkmask |= SupportRAMDAC2_202;
+              }
+           }
+        }
 
-     } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 
-       checkmask |= SupportLCD;
-       if(HwInfo->jChipType >= SIS_315H) {
-          if(SiS_Pr->SiS_VBType & VB_SISVB) {
-             if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-                if(modeid == 0x2e) checkmask |= Support64048060Hz;
-             }
-          }
-       }
+        checkmask |= SupportLCD;
+        if(SiS_Pr->ChipType >= SIS_315H) {
+           if(SiS_Pr->SiS_VBType & VB_SISVB) {
+              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+                 if(modeid == 0x2e) checkmask |= Support64048060Hz;
+              }
+           }
+        }
 
-     } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-       checkmask |= SupportHiVision;
+        checkmask |= SupportHiVision;
 
-     } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
+      } else if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750|SetCRT2ToAVIDEO|SetCRT2ToSVIDEO|SetCRT2ToSCART)) {
 
-        checkmask |= SupportTV;
-       if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-          checkmask |= SupportTV1024;
-          if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-             if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-                checkmask |= SupportYPbPr750p;
-             }
-          }
-       }
+        checkmask |= SupportTV;
+        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+           checkmask |= SupportTV1024;
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+              if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+                 checkmask |= SupportYPbPr750p;
+              }
+           }
+        }
 
-     }
+      }
 
-  } else {     /* LVDS */
+   } else {    /* LVDS */
 
-     if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-           checkmask |= SupportCHTV;
-       }
-     }
+      if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+           checkmask |= SupportCHTV;
+        }
+      }
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-       checkmask |= SupportLCD;
-     }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+        checkmask |= SupportLCD;
+      }
 
-  }
+   }
 
-  /* Look backwards in table for matching CRT2 mode */
-  for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
-     infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-     if(infoflag & checkmask) return TRUE;
-     if((*i) == 0) break;
-  }
+   /* Look backwards in table for matching CRT2 mode */
+   for(; SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID == modeid; (*i)--) {
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+      if(infoflag & checkmask) return TRUE;
+      if((*i) == 0) break;
+   }
 
-  /* Look through the whole mode-section of the table from the beginning
-   * for a matching CRT2 mode if no mode was found yet.
-   */
-  for((*i) = 0; ; (*i)++) {
-     if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
-     infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
-     if(infoflag & checkmask) return TRUE;
-  }
-  return FALSE;
+   /* Look through the whole mode-section of the table from the beginning
+    * for a matching CRT2 mode if no mode was found yet.
+    */
+   for((*i) = 0; ; (*i)++) {
+      if(SiS_Pr->SiS_RefIndex[RRTI + (*i)].ModeID != modeid) break;
+      infoflag = SiS_Pr->SiS_RefIndex[RRTI + (*i)].Ext_InfoFlag;
+      if(infoflag & checkmask) return TRUE;
+   }
+   return FALSE;
 }
 
 /*********************************************/
 /*              Get rate index               */
 /*********************************************/
 
-USHORT
-SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-               PSIS_HW_INFO HwInfo)
-{
-  SHORT  LCDRefreshIndex[] = { 0x00, 0x00, 0x01, 0x01,
-                               0x01, 0x01, 0x01, 0x01,
-                              0x01, 0x01, 0x01, 0x01,
-                              0x01, 0x01, 0x01, 0x01,
-                              0x00, 0x00, 0x00, 0x00 };
-  USHORT RRTI,i,backup_i;
-  USHORT modeflag,index,temp,backupindex;
+unsigned short
+SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
+{
+   unsigned short RRTI,i,backup_i;
+   unsigned short modeflag,index,temp,backupindex;
+   static const unsigned short LCDRefreshIndex[] = {
+               0x00, 0x00, 0x01, 0x01,
+               0x01, 0x01, 0x01, 0x01,
+               0x01, 0x01, 0x01, 0x01,
+               0x01, 0x01, 0x01, 0x01,
+               0x00, 0x00, 0x00, 0x00
+   };
 
-  /* Do NOT check for UseCustomMode here, will skrew up FIFO */
-  if(ModeNo == 0xfe) return 0;
+   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
+   if(ModeNo == 0xfe) return 0;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
+   if(ModeNo <= 0x13) {
+      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+   } else {
+      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
 
-  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-       if(modeflag & HalfDCLK) return 0;
-     }
-  }
+   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+        if(modeflag & HalfDCLK) return 0;
+      }
+   }
 
-  if(ModeNo < 0x14) return 0xFFFF;
+   if(ModeNo < 0x14) return 0xFFFF;
 
-  index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
-  backupindex = index;
+   index = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x33) >> SiS_Pr->SiS_SelectCRT2Rate) & 0x0F;
+   backupindex = index;
 
-  if(index > 0) index--;
+   if(index > 0) index--;
 
-  if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-          if(SiS_Pr->SiS_VBType & VB_NoLCD)            index = 0;
-          else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
-       }
-       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-          if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
-              temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
-              if(index > temp) index = temp;
-          }
-       }
-     } else {
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
-       if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
-        }
-     }
-  }
+   if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+           if(SiS_Pr->SiS_VBType & VB_NoLCD)            index = 0;
+           else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index = backupindex = 0;
+        }
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+           if(!(SiS_Pr->SiS_VBType & VB_NoLCD)) {
+              temp = LCDRefreshIndex[SiS_GetBIOSLCDResInfo(SiS_Pr)];
+              if(index > temp) index = temp;
+           }
+        }
+      } else {
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) index = 0;
+        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) index = 0;
+        }
+      }
+   }
 
-  RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
-  ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
+   RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+   ModeNo = SiS_Pr->SiS_RefIndex[RRTI].ModeID;
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
-        if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
-            (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
-           if(backupindex <= 1) RRTI++;
-        }
-     }
-  }
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(!(SiS_Pr->SiS_VBInfo & DriverMode)) {
+        if( (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x105) ||
+            (SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_VESAID == 0x107) ) {
+           if(backupindex <= 1) RRTI++;
+        }
+      }
+   }
 
-  i = 0;
-  do {
-     if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
-     temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
-     temp &= ModeTypeMask;
-     if(temp < SiS_Pr->SiS_ModeType) break;
-     i++;
-     index--;
-  } while(index != 0xFFFF);
-
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-       temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
-       if(temp & InterlaceMode) i++;
-     }
-  }
+   i = 0;
+   do {
+      if(SiS_Pr->SiS_RefIndex[RRTI + i].ModeID != ModeNo) break;
+      temp = SiS_Pr->SiS_RefIndex[RRTI + i].Ext_InfoFlag;
+      temp &= ModeTypeMask;
+      if(temp < SiS_Pr->SiS_ModeType) break;
+      i++;
+      index--;
+   } while(index != 0xFFFF);
+
+   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+        temp = SiS_Pr->SiS_RefIndex[RRTI + i - 1].Ext_InfoFlag;
+        if(temp & InterlaceMode) i++;
+      }
+   }
 
-  i--;
+   i--;
 
-  if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
-     backup_i = i;
-     if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i, HwInfo))) {
-       i = backup_i;
-     }
-  }
+   if((SiS_Pr->SiS_SetFlag & ProgrammingCRT2) && (!(SiS_Pr->SiS_VBInfo & DisableCRT2Display))) {
+      backup_i = i;
+      if(!(SiS_AdjustCRT2Rate(SiS_Pr, ModeNo, ModeIdIndex, RRTI, &i))) {
+        i = backup_i;
+      }
+   }
 
-  return(RRTI + i);
+   return (RRTI + i);
 }
 
 /*********************************************/
@@ -378,15 +389,15 @@ SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SaveCRT2Info(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-  USHORT temp1,temp2;
+   unsigned short temp1, temp2;
 
-  /* Store CRT1 ModeNo in CR34 */
-  SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
-  temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
-  temp2 = ~(SetInSlaveMode >> 8);
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
+   /* Store CRT1 ModeNo in CR34 */
+   SiS_SetReg(SiS_Pr->SiS_P3d4,0x34,ModeNo);
+   temp1 = (SiS_Pr->SiS_VBInfo & SetInSlaveMode) >> 8;
+   temp2 = ~(SetInSlaveMode >> 8);
+   SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x31,temp2,temp1);
 }
 
 /*********************************************/
@@ -395,35 +406,35 @@ SiS_SaveCRT2Info(SiS_Private *SiS_Pr, USHORT ModeNo)
 
 #ifdef SIS300
 static BOOLEAN
-SiS_CR36BIOSWord23b(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CR36BIOSWord23b(struct SiS_Private *SiS_Pr)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT temp,temp1;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp,temp1;
 
-  if(SiS_Pr->SiS_UseROM) {
-     if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-        temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
-        temp1 = SISGETROMW(0x23b);
-        if(temp1 & temp) return TRUE;
-     }
-  }
-  return FALSE;
+   if(SiS_Pr->SiS_UseROM) {
+      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+        temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+        temp1 = SISGETROMW(0x23b);
+        if(temp1 & temp) return TRUE;
+      }
+   }
+   return FALSE;
 }
 
 static BOOLEAN
-SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT temp,temp1;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp,temp1;
 
-  if(SiS_Pr->SiS_UseROM) {
-     if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-        temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
-        temp1 = SISGETROMW(0x23d);
-        if(temp1 & temp) return TRUE;
-     }
-  }
-  return FALSE;
+   if(SiS_Pr->SiS_UseROM) {
+      if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
+        temp = 1 << ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) & 0x0f);
+        temp1 = SISGETROMW(0x23d);
+        if(temp1 & temp) return TRUE;
+      }
+   }
+   return FALSE;
 }
 #endif
 
@@ -432,85 +443,76 @@ SiS_CR36BIOSWord23d(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 void
-SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime)
+SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime)
 {
-  USHORT i, j;
+   unsigned int i, j;
 
-  for(i=0; i<delaytime; i++) {
-     j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
-  }
+   for(i = 0; i < delaytime; i++) {
+      j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05);
+   }
 }
 
 #if defined(SIS300) || defined(SIS315H)
 static void
-SiS_GenericDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_GenericDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 {
-  USHORT temp,flag;
-
-  flag = SiS_GetRegByte(0x61) & 0x10;
-
-  while(delay) {
-     temp = SiS_GetRegByte(0x61) & 0x10;
-     if(temp == flag) continue;
-     flag = temp;
-     delay--;
-  }
+   SiS_DDC2Delay(SiS_Pr, delay * 36);
 }
 #endif
 
 #ifdef SIS315H
 static void
-SiS_LongDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_LongDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 {
-  while(delay--) {
-     SiS_GenericDelay(SiS_Pr,0x19df);
-  }
+   while(delay--) {
+      SiS_GenericDelay(SiS_Pr, 6623);
+   }
 }
 #endif
 
 #if defined(SIS300) || defined(SIS315H)
 static void
-SiS_ShortDelay(SiS_Private *SiS_Pr, USHORT delay)
+SiS_ShortDelay(struct SiS_Private *SiS_Pr, unsigned short delay)
 {
-  while(delay--) {
-     SiS_GenericDelay(SiS_Pr,0x42);
-  }
+   while(delay--) {
+      SiS_GenericDelay(SiS_Pr, 66);
+   }
 }
 #endif
 
 static void
-SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
+SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
 {
 #if defined(SIS300) || defined(SIS315H)
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT PanelID, DelayIndex, Delay=0;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short PanelID, DelayIndex, Delay=0;
 #endif
 
-  if(HwInfo->jChipType < SIS_315H) {
+   if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300
 
       PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
       if(SiS_Pr->SiS_VBType & VB_SISVB) {
-         if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
-         if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
+        if(SiS_Pr->SiS_VBType & VB_SIS301) PanelID &= 0xf7;
+        if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x18) & 0x10)) PanelID = 0x12;
       }
       DelayIndex = PanelID >> 4;
       if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
-         Delay = 3;
+        Delay = 3;
       } else {
-         if(DelayTime >= 2) DelayTime -= 2;
-         if(!(DelayTime & 0x01)) {
-                   Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
-         } else {
-                   Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
-         }
+        if(DelayTime >= 2) DelayTime -= 2;
+        if(!(DelayTime & 0x01)) {
+           Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+        } else {
+           Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+        }
         if(SiS_Pr->SiS_UseROM) {
-            if(ROMAddr[0x220] & 0x40) {
-               if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
-               else                   Delay = (USHORT)ROMAddr[0x226];
-            }
-         }
+           if(ROMAddr[0x220] & 0x40) {
+              if(!(DelayTime & 0x01)) Delay = (unsigned short)ROMAddr[0x225];
+              else                    Delay = (unsigned short)ROMAddr[0x226];
+           }
+        }
       }
       SiS_ShortDelay(SiS_Pr, Delay);
 
@@ -520,23 +522,23 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
 
 #ifdef SIS315H
 
-      if((HwInfo->jChipType >= SIS_661)    ||
-         (HwInfo->jChipType <= SIS_315PRO) ||
-        (HwInfo->jChipType == SIS_330)    ||
+      if((SiS_Pr->ChipType >= SIS_661)    ||
+        (SiS_Pr->ChipType <= SIS_315PRO) ||
+        (SiS_Pr->ChipType == SIS_330)    ||
         (SiS_Pr->SiS_ROMNew)) {
 
-         if(!(DelayTime & 0x01)) {
+        if(!(DelayTime & 0x01)) {
            SiS_DDC2Delay(SiS_Pr, 0x1000);
-         } else {
+        } else {
            SiS_DDC2Delay(SiS_Pr, 0x4000);
-         }
+        }
 
       } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
-         (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+        (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {                  /* 315 series, LVDS; Special */
 
-         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-            PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
+           PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
            if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1b) & 0x10)) PanelID = 0x12;
            }
@@ -546,35 +548,35 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
               DelayIndex = PanelID >> 4;
            }
            if((DelayTime >= 2) && ((PanelID & 0x0f) == 1))  {
-               Delay = 3;
-            } else {
-               if(DelayTime >= 2) DelayTime -= 2;
-               if(!(DelayTime & 0x01)) {
-                         Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
-               } else {
-                         Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
-               }
+              Delay = 3;
+           } else {
+              if(DelayTime >= 2) DelayTime -= 2;
+              if(!(DelayTime & 0x01)) {
+                 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[0];
+               } else {
+                 Delay = SiS_Pr->SiS_PanelDelayTblLVDS[DelayIndex].timer[1];
+              }
               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-                  if(ROMAddr[0x13c] & 0x40) {
-                     if(!(DelayTime & 0x01)) {
-                       Delay = (USHORT)ROMAddr[0x17e];
-                     } else {
-                       Delay = (USHORT)ROMAddr[0x17f];
-                     }
-                  }
-               }
-            }
+                 if(ROMAddr[0x13c] & 0x40) {
+                    if(!(DelayTime & 0x01)) {
+                       Delay = (unsigned short)ROMAddr[0x17e];
+                    } else {
+                       Delay = (unsigned short)ROMAddr[0x17f];
+                    }
+                 }
+              }
+           }
            SiS_ShortDelay(SiS_Pr, Delay);
         }
 
       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {                       /* 315 series, all bridges */
 
         DelayIndex = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4;
-         if(!(DelayTime & 0x01)) {
-                   Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
-         } else {
-                   Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
-         }
+        if(!(DelayTime & 0x01)) {
+           Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
+        } else {
+           Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[1];
+        }
         Delay <<= 8;
         SiS_DDC2Delay(SiS_Pr, Delay);
 
@@ -587,12 +589,11 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DelayTime)
 
 #ifdef SIS315H
 static void
-SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                      USHORT DelayTime, USHORT DelayLoop)
+SiS_PanelDelayLoop(struct SiS_Private *SiS_Pr, unsigned short DelayTime, unsigned short DelayLoop)
 {
    int i;
-   for(i=0; i<DelayLoop; i++) {
-      SiS_PanelDelay(SiS_Pr, HwInfo, DelayTime);
+   for(i = 0; i < DelayLoop; i++) {
+      SiS_PanelDelay(SiS_Pr, DelayTime);
    }
 }
 #endif
@@ -602,86 +603,86 @@ SiS_PanelDelayLoop(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 /*********************************************/
 
 void
-SiS_WaitRetrace1(SiS_Private *SiS_Pr)
+SiS_WaitRetrace1(struct SiS_Private *SiS_Pr)
 {
-  USHORT watchdog;
+   unsigned short watchdog;
 
-  if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
-  if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
+   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
+   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
 
-  watchdog = 65535;
-  while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
-  watchdog = 65535;
-  while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
+   watchdog = 65535;
+   while((SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08) && --watchdog);
+   watchdog = 65535;
+   while((!(SiS_GetRegByte(SiS_Pr->SiS_P3da) & 0x08)) && --watchdog);
 }
 
 #if defined(SIS300) || defined(SIS315H)
 static void
-SiS_WaitRetrace2(SiS_Private *SiS_Pr, USHORT reg)
+SiS_WaitRetrace2(struct SiS_Private *SiS_Pr, unsigned short reg)
 {
-  USHORT watchdog;
+   unsigned short watchdog;
 
-  watchdog = 65535;
-  while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
-  watchdog = 65535;
-  while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
+   watchdog = 65535;
+   while((SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02) && --watchdog);
+   watchdog = 65535;
+   while((!(SiS_GetReg(SiS_Pr->SiS_Part1Port,reg) & 0x02)) && --watchdog);
 }
 #endif
 
 static void
-SiS_WaitVBRetrace(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_WaitVBRetrace(struct SiS_Private *SiS_Pr)
 {
-  if(HwInfo->jChipType < SIS_315H) {
+   if(SiS_Pr->ChipType < SIS_315H) {
 #ifdef SIS300
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-        if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
-     }
-     if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
-        SiS_WaitRetrace1(SiS_Pr);
-     } else {
-        SiS_WaitRetrace2(SiS_Pr, 0x25);
-     }
+      if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+        if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x20)) return;
+      }
+      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x80)) {
+        SiS_WaitRetrace1(SiS_Pr);
+      } else {
+        SiS_WaitRetrace2(SiS_Pr, 0x25);
+      }
 #endif
-  } else {
+   } else {
 #ifdef SIS315H
-     if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
-        SiS_WaitRetrace1(SiS_Pr);
-     } else {
-        SiS_WaitRetrace2(SiS_Pr, 0x30);
-     }
+      if(!(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x40)) {
+        SiS_WaitRetrace1(SiS_Pr);
+      } else {
+        SiS_WaitRetrace2(SiS_Pr, 0x30);
+      }
 #endif
-  }
+   }
 }
 
 static void
-SiS_VBWait(SiS_Private *SiS_Pr)
+SiS_VBWait(struct SiS_Private *SiS_Pr)
 {
-  USHORT tempal,temp,i,j;
+   unsigned short tempal,temp,i,j;
 
-  temp = 0;
-  for(i=0; i<3; i++) {
-    for(j=0; j<100; j++) {
-       tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
-       if(temp & 0x01) {
-          if((tempal & 0x08))  continue;
-          else break;
-       } else {
-          if(!(tempal & 0x08)) continue;
-          else break;
-       }
-    }
-    temp ^= 0x01;
-  }
+   temp = 0;
+   for(i = 0; i < 3; i++) {
+     for(j = 0; j < 100; j++) {
+        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
+        if(temp & 0x01) {
+          if((tempal & 0x08))  continue;
+          else break;
+        } else {
+          if(!(tempal & 0x08)) continue;
+          else break;
+        }
+     }
+     temp ^= 0x01;
+   }
 }
 
 static void
-SiS_VBLongWait(SiS_Private *SiS_Pr)
+SiS_VBLongWait(struct SiS_Private *SiS_Pr)
 {
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     SiS_VBWait(SiS_Pr);
-  } else {
-     SiS_WaitRetrace1(SiS_Pr);
-  }
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+      SiS_VBWait(SiS_Pr);
+   } else {
+      SiS_WaitRetrace1(SiS_Pr);
+   }
 }
 
 /*********************************************/
@@ -690,237 +691,225 @@ SiS_VBLongWait(SiS_Private *SiS_Pr)
 
 #ifdef SIS300
 static BOOLEAN
-SiS_Is301B(SiS_Private *SiS_Pr)
+SiS_Is301B(struct SiS_Private *SiS_Pr)
 {
-  if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
-  return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
+   return FALSE;
 }
 #endif
 
 static BOOLEAN
-SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_CRT2IsLCD(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
-
-  if(HwInfo->jChipType == SIS_730) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13);
-     if(flag & 0x20) return TRUE;
-  }
-  flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-  if(flag & 0x20) return TRUE;
-  return FALSE;
+   if(SiS_Pr->ChipType == SIS_730) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x20) return TRUE;
+   }
+   if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x30) & 0x20) return TRUE;
+   return FALSE;
 }
 
 BOOLEAN
-SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsDualEdge(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
-  USHORT flag;
-
-  if(HwInfo->jChipType >= SIS_315H) {
-     if((HwInfo->jChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
-        flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-        if(flag & EnableDualEdge) return TRUE;
-     }
-  }
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if((SiS_Pr->ChipType != SIS_650) || (SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0)) {
+        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableDualEdge) return TRUE;
+      }
+   }
 #endif
-  return FALSE;
+   return FALSE;
 }
 
 BOOLEAN
-SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsVAMode(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
-  USHORT flag;
+   unsigned short flag;
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-     if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
-  }
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      if((flag & EnableDualEdge) && (flag & SetToLCDA)) return TRUE;
+   }
 #endif
-  return FALSE;
+   return FALSE;
 }
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsVAorLCD(struct SiS_Private *SiS_Pr)
 {
-  if(SiS_IsVAMode(SiS_Pr,HwInfo))   return TRUE;
-  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
-  return FALSE;
+   if(SiS_IsVAMode(SiS_Pr))  return TRUE;
+   if(SiS_CRT2IsLCD(SiS_Pr)) return TRUE;
+   return FALSE;
 }
 #endif
 
 static BOOLEAN
-SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsDualLink(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
-  if(HwInfo->jChipType >= SIS_315H) {
-     if((SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ||
-        (SiS_IsVAMode(SiS_Pr, HwInfo))) {
-        if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
-     }
-  }
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if((SiS_CRT2IsLCD(SiS_Pr)) ||
+         (SiS_IsVAMode(SiS_Pr))) {
+        if(SiS_Pr->SiS_LCDInfo & LCDDualLink) return TRUE;
+      }
+   }
 #endif
-  return FALSE;
+   return FALSE;
 }
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_TVEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_TVEnabled(struct SiS_Private *SiS_Pr)
 {
-  if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
-  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS301LV302LV)) {
-     if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
-  }
-  return FALSE;
+   if((SiS_GetReg(SiS_Pr->SiS_Part2Port,0x00) & 0x0f) != 0x0c) return TRUE;
+   if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+      if(SiS_GetReg(SiS_Pr->SiS_Part2Port,0x4d) & 0x10) return TRUE;
+   }
+   return FALSE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_LCDAEnabled(struct SiS_Private *SiS_Pr)
 {
-  if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
-  return FALSE;
+   if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x13) & 0x04) return TRUE;
+   return FALSE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_WeHaveBacklightCtrl(struct SiS_Private *SiS_Pr)
 {
-  if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
-  }
-  return FALSE;
+   if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
+   }
+   return FALSE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_IsNotM650orLater(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsNotM650orLater(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
+   unsigned short flag;
 
-  if(HwInfo->jChipType == SIS_650) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f);
-     flag &= 0xF0;
-     /* Check for revision != A0 only */
-     if((flag == 0xe0) || (flag == 0xc0) ||
-        (flag == 0xb0) || (flag == 0x90)) return FALSE;
-  } else if(HwInfo->jChipType >= SIS_661) return FALSE;
-  return TRUE;
+   if(SiS_Pr->ChipType == SIS_650) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xf0;
+      /* Check for revision != A0 only */
+      if((flag == 0xe0) || (flag == 0xc0) ||
+         (flag == 0xb0) || (flag == 0x90)) return FALSE;
+   } else if(SiS_Pr->ChipType >= SIS_661) return FALSE;
+   return TRUE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_IsYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsYPbPr(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
-
-  if(HwInfo->jChipType >= SIS_315H) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-     if(flag & EnableCHYPbPr) return TRUE;  /* = YPrPb = 0x08 */
-  }
-  return FALSE;
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      /* YPrPb = 0x08 */
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHYPbPr) return TRUE;
+   }
+   return FALSE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_IsChScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsChScart(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
-
-  if(HwInfo->jChipType >= SIS_315H) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-     if(flag & EnableCHScart) return TRUE;  /* = Scart = 0x04 */
-  }
-  return FALSE;
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      /* Scart = 0x04 */
+      if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & EnableCHScart) return TRUE;
+   }
+   return FALSE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_IsTVOrYPbPrOrScart(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsTVOrYPbPrOrScart(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
+   unsigned short flag;
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-     if(flag & SetCRT2ToTV)        return TRUE;
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-     if(flag & EnableCHYPbPr)      return TRUE;  /* = YPrPb = 0x08 */
-     if(flag & EnableCHScart)      return TRUE;  /* = Scart = 0x04 - TW */
-  } else {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-     if(flag & SetCRT2ToTV)        return TRUE;
-  }
-  return FALSE;
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToTV)        return TRUE;
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      if(flag & EnableCHYPbPr)      return TRUE;  /* = YPrPb = 0x08 */
+      if(flag & EnableCHScart)      return TRUE;  /* = Scart = 0x04 - TW */
+   } else {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToTV)        return TRUE;
+   }
+   return FALSE;
 }
 #endif
 
 #ifdef SIS315H
 static BOOLEAN
-SiS_IsLCDOrLCDA(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_IsLCDOrLCDA(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
+   unsigned short flag;
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-     if(flag & SetCRT2ToLCD) return TRUE;
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-     if(flag & SetToLCDA)    return TRUE;
-  } else {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-     if(flag & SetCRT2ToLCD) return TRUE;
-  }
-  return FALSE;
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToLCD) return TRUE;
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+      if(flag & SetToLCDA)    return TRUE;
+   } else {
+      flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+      if(flag & SetCRT2ToLCD) return TRUE;
+   }
+   return FALSE;
 }
 #endif
 
 static BOOLEAN
-SiS_BridgeIsOn(SiS_Private *SiS_Pr)
+SiS_HaveBridge(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
+   unsigned short flag;
 
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     return TRUE;
-  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-     if((flag == 1) || (flag == 2)) return TRUE;
-  }
-  return FALSE;
+   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+      return TRUE;
+   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
+      if((flag == 1) || (flag == 2)) return TRUE;
+   }
+   return FALSE;
 }
 
 static BOOLEAN
-SiS_BridgeIsEnabled(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_BridgeIsEnabled(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag;
+   unsigned short flag;
 
-  if(SiS_BridgeIsOn(SiS_Pr)) {
-     flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-     if(HwInfo->jChipType < SIS_315H) {
-       flag &= 0xa0;
-       if((flag == 0x80) || (flag == 0x20)) return TRUE;
-     } else {
-       flag &= 0x50;
-       if((flag == 0x40) || (flag == 0x10)) return TRUE;
-     }
-  }
-  return FALSE;
+   if(SiS_HaveBridge(SiS_Pr)) {
+      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+      if(SiS_Pr->ChipType < SIS_315H) {
+       flag &= 0xa0;
+       if((flag == 0x80) || (flag == 0x20)) return TRUE;
+      } else {
+       flag &= 0x50;
+       if((flag == 0x40) || (flag == 0x10)) return TRUE;
+      }
+   }
+   return FALSE;
 }
 
 static BOOLEAN
-SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
+SiS_BridgeInSlavemode(struct SiS_Private *SiS_Pr)
 {
-  USHORT flag1;
+   unsigned short flag1;
 
-  flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
-  if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
-  return FALSE;
+   flag1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31);
+   if(flag1 & (SetInSlaveMode >> 8)) return TRUE;
+   return FALSE;
 }
 
 /*********************************************/
@@ -928,119 +917,97 @@ SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
 /*********************************************/
 
 /* Setup general purpose IO for Chrontel communication */
+#ifdef SIS300
 void
-SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo)
+SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo)
 {
-   unsigned long  acpibase;
+   unsigned int   acpibase;
    unsigned short temp;
 
    if(!(SiS_Pr->SiS_ChSW)) return;
 
-#ifdef LINUX_KERNEL
-   SiS_SetRegLong(0xcf8,0x80000874);                  /* get ACPI base */
-   acpibase = SiS_GetRegLong(0xcfc);
+#ifdef SIS_LINUX_KERNEL
+   acpibase = sisfb_read_lpc_pci_dword(SiS_Pr, 0x74);
 #else
    acpibase = pciReadLong(0x00000800, 0x74);
 #endif
    acpibase &= 0xFFFF;
-   temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));  /* ACPI register 0x3c: GP Event 1 I/O mode select */
+   if(!acpibase) return;
+   temp = SiS_GetRegShort((acpibase + 0x3c));  /* ACPI register 0x3c: GP Event 1 I/O mode select */
    temp &= 0xFEFF;
-   SiS_SetRegShort((USHORT)(acpibase + 0x3c), temp);
-   temp = SiS_GetRegShort((USHORT)(acpibase + 0x3c));
-   temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));  /* ACPI register 0x3a: GP Pin Level (low/high) */
+   SiS_SetRegShort((acpibase + 0x3c), temp);
+   temp = SiS_GetRegShort((acpibase + 0x3c));
+   temp = SiS_GetRegShort((acpibase + 0x3a));  /* ACPI register 0x3a: GP Pin Level (low/high) */
    temp &= 0xFEFF;
    if(!(myvbinfo & SetCRT2ToTV)) temp |= 0x0100;
-   SiS_SetRegShort((USHORT)(acpibase + 0x3a), temp);
-   temp = SiS_GetRegShort((USHORT)(acpibase + 0x3a));
+   SiS_SetRegShort((acpibase + 0x3a), temp);
+   temp = SiS_GetRegShort((acpibase + 0x3a));
 }
+#endif
 
 void
-SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-              PSIS_HW_INFO HwInfo, int checkcrt2mode)
+SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, int checkcrt2mode)
 {
-  USHORT tempax,tempbx,temp;
-  USHORT modeflag, resinfo=0;
+   unsigned short tempax, tempbx, temp;
+   unsigned short modeflag, resinfo = 0;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
+   SiS_Pr->SiS_SetFlag = 0;
 
-  SiS_Pr->SiS_SetFlag = 0;
+   modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
 
-  SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
+   SiS_Pr->SiS_ModeType = modeflag & ModeTypeMask;
 
-  tempbx = 0;
-  if(SiS_BridgeIsOn(SiS_Pr)) {
-       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-#if 0
-       if(HwInfo->jChipType < SIS_661) {
-          /* NO - YPbPr not set yet ! */
-          if(SiS_Pr->SiS_YPbPr & <all ypbpr except 525i>) {
-             temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode);       /* 0x83 */
-             temp |= SetCRT2ToHiVision;                                        /* 0x80 */
-          }
-          if(SiS_Pr->SiS_YPbPr & <ypbpr525i>) {
-             temp &= (SetCRT2ToHiVision | SwitchCRT2 | SetSimuScanMode);       /* 0x83 */
-             temp |= SetCRT2ToSVIDEO;                                          /* 0x08 */
-          }
-       }
-#endif
-       tempbx |= temp;
-       tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
-        tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
-       tempbx |= tempax;
+   if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
+
+   tempbx = 0;
+
+   if(SiS_HaveBridge(SiS_Pr)) {
+
+       temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+       tempbx |= temp;
+       tempax = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) << 8;
+       tempax &= (DriverMode | LoadDACFlag | SetNotSimuMode | SetPALTV);
+       tempbx |= tempax;
 
 #ifdef SIS315H
-       if(HwInfo->jChipType >= SIS_315H) {
-          if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
+       if(SiS_Pr->ChipType >= SIS_315H) {
+          if(SiS_Pr->SiS_VBType & VB_SISLCDA) {
              if(ModeNo == 0x03) {
-                /* Mode 0x03 is never in driver mode */
+                /* Mode 0x03 is never in driver mode */
                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
              }
              if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
-                /* Reset LCDA setting if not driver mode */
+                /* Reset LCDA setting if not driver mode */
                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
              }
              if(IS_SIS650) {
-                if(SiS_Pr->SiS_UseLCDA) {
+                if(SiS_Pr->SiS_UseLCDA) {
                    if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x5f) & 0xF0) {
                       if((ModeNo <= 0x13) || (!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8)))) {
-                         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
+                         SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x38,(EnableDualEdge | SetToLCDA));
                       }
                    }
                 }
              }
              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-                     if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
-                tempbx |= SetCRT2ToLCDA;
+             if((temp & (EnableDualEdge | SetToLCDA)) == (EnableDualEdge | SetToLCDA)) {
+                tempbx |= SetCRT2ToLCDA;
              }
           }
 
-          if(SiS_Pr->SiS_VBType & (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)) {
-             tempbx &= ~(SetCRT2ToRAMDAC);
-          }
-
-          if(HwInfo->jChipType >= SIS_661) {
+          if(SiS_Pr->ChipType >= SIS_661) { /* New CR layout */
              tempbx &= ~(SetCRT2ToYPbPr525750 | SetCRT2ToHiVision);
-             temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-             if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
-                if(temp & 0x04) {
-                   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
-                   if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
-                   else             tempbx |= SetCRT2ToYPbPr525750;
-                }
-             } else if(SiS_Pr->SiS_VBType & VB_SISHIVISION) {
-                if(temp & 0x04) {
-                   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
-                   if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+             if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x38) & 0x04) {
+                temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35) & 0xe0;
+                if(temp == 0x60) tempbx |= SetCRT2ToHiVision;
+                else if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+                   tempbx |= SetCRT2ToYPbPr525750;
                 }
              }
-          }
+          }
 
           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
@@ -1048,7 +1015,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 tempbx |= SetCRT2ToLCDA;
              }
              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-                if(temp & EnableCHYPbPr) {
+                if(temp & EnableCHYPbPr) {
                    tempbx |= SetCRT2ToCHYPbPr;
                 }
              }
@@ -1057,44 +1024,49 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
 #endif  /* SIS315H */
 
-       if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(!(SiS_Pr->SiS_VBType & VB_SISVGA2)) {
+          tempbx &= ~(SetCRT2ToRAMDAC);
+       }
+
+       if(SiS_Pr->SiS_VBType & VB_SISVB) {
           temp = SetCRT2ToSVIDEO   |
-                 SetCRT2ToAVIDEO   |
-                 SetCRT2ToSCART    |
-                 SetCRT2ToLCDA     |
-                 SetCRT2ToLCD      |
-                 SetCRT2ToRAMDAC   |
-                  SetCRT2ToHiVision |
+                 SetCRT2ToAVIDEO   |
+                 SetCRT2ToSCART    |
+                 SetCRT2ToLCDA     |
+                 SetCRT2ToLCD      |
+                 SetCRT2ToRAMDAC   |
+                 SetCRT2ToHiVision |
                  SetCRT2ToYPbPr525750;
-       } else {
-           if(HwInfo->jChipType >= SIS_315H) {
-              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-                temp = SetCRT2ToAVIDEO |
+       } else {
+          if(SiS_Pr->ChipType >= SIS_315H) {
+             if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+                temp = SetCRT2ToAVIDEO |
                        SetCRT2ToSVIDEO |
                        SetCRT2ToSCART  |
                        SetCRT2ToLCDA   |
                        SetCRT2ToLCD    |
                        SetCRT2ToCHYPbPr;
-             } else {
-                temp = SetCRT2ToLCDA   |
+             } else {
+                temp = SetCRT2ToLCDA   |
                        SetCRT2ToLCD;
              }
           } else {
-             if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-                temp = SetCRT2ToTV | SetCRT2ToLCD;
-              } else {
-                temp = SetCRT2ToLCD;
+             if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+                temp = SetCRT2ToTV | SetCRT2ToLCD;
+             } else {
+                temp = SetCRT2ToLCD;
              }
           }
-       }
+       }
+
+       if(!(tempbx & temp)) {
+          tempax = DisableCRT2Display;
+          tempbx = 0;
+       }
 
-       if(!(tempbx & temp)) {
-          tempax = DisableCRT2Display;
-          tempbx = 0;
-       }
+       if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-       if(SiS_Pr->SiS_VBType & VB_SISVB) {
-          USHORT clearmask = ( DriverMode         |
+          unsigned short clearmask = ( DriverMode |
                                DisableCRT2Display |
                                LoadDACFlag        |
                                SetNotSimuMode     |
@@ -1102,106 +1074,104 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                                SetPALTV           |
                                SwitchCRT2         |
                                SetSimuScanMode );
-          if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
+
+          if(tempbx & SetCRT2ToLCDA)        tempbx &= (clearmask | SetCRT2ToLCDA);
           if(tempbx & SetCRT2ToRAMDAC)      tempbx &= (clearmask | SetCRT2ToRAMDAC);
           if(tempbx & SetCRT2ToLCD)         tempbx &= (clearmask | SetCRT2ToLCD);
           if(tempbx & SetCRT2ToSCART)       tempbx &= (clearmask | SetCRT2ToSCART);
           if(tempbx & SetCRT2ToHiVision)    tempbx &= (clearmask | SetCRT2ToHiVision);
           if(tempbx & SetCRT2ToYPbPr525750) tempbx &= (clearmask | SetCRT2ToYPbPr525750);
-       } else {
-          if(HwInfo->jChipType >= SIS_315H) {
+
+       } else {
+
+          if(SiS_Pr->ChipType >= SIS_315H) {
              if(tempbx & SetCRT2ToLCDA) {
-                tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
+                tempbx &= (0xFF00|SwitchCRT2|SetSimuScanMode);
              }
           }
-          if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-              if(tempbx & SetCRT2ToTV) {
-                tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
+          if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+             if(tempbx & SetCRT2ToTV) {
+                tempbx &= (0xFF00|SetCRT2ToTV|SwitchCRT2|SetSimuScanMode);
              }
-          }
-          if(tempbx & SetCRT2ToLCD) {
-              tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
           }
-          if(HwInfo->jChipType >= SIS_315H) {
+          if(tempbx & SetCRT2ToLCD) {
+             tempbx &= (0xFF00|SetCRT2ToLCD|SwitchCRT2|SetSimuScanMode);
+          }
+          if(SiS_Pr->ChipType >= SIS_315H) {
              if(tempbx & SetCRT2ToLCDA) {
                 tempbx |= SetCRT2ToLCD;
              }
           }
+
        }
 
-       if(tempax & DisableCRT2Display) {
-          if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
-              tempbx = SetSimuScanMode | DisableCRT2Display;
-          }
-       }
+       if(tempax & DisableCRT2Display) {
+          if(!(tempbx & (SwitchCRT2 | SetSimuScanMode))) {
+             tempbx = SetSimuScanMode | DisableCRT2Display;
+          }
+       }
 
-       if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
+       if(!(tempbx & DriverMode)) tempbx |= SetSimuScanMode;
 
        /* LVDS/CHRONTEL (LCD/TV) and 301BDH (LCD) can only be slave in 8bpp modes */
        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
           if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
               ((SiS_Pr->SiS_VBType & VB_NoLCD) && (tempbx & SetCRT2ToLCD)) ) {
-              modeflag &= (~CRT2Mode);
+             modeflag &= (~CRT2Mode);
           }
        }
 
-       if(!(tempbx & SetSimuScanMode)) {
-          if(tempbx & SwitchCRT2) {
-              if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
-                if( (HwInfo->jChipType >= SIS_315H) &&
-                    (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
-                   if(resinfo != SIS_RI_1600x1200) {
-                       tempbx |= SetSimuScanMode;
-                   }
-                } else {
-                   tempbx |= SetSimuScanMode;
-                }
+       if(!(tempbx & SetSimuScanMode)) {
+          if(tempbx & SwitchCRT2) {
+             if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+                if(resinfo != SIS_RI_1600x1200) {
+                   tempbx |= SetSimuScanMode;
+                }
               }
-          } else {
-              if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
-                if(!(tempbx & DriverMode)) {
-                   if(SiS_BridgeInSlavemode(SiS_Pr)) {
+          } else {
+             if(SiS_BridgeIsEnabled(SiS_Pr)) {
+                if(!(tempbx & DriverMode)) {
+                   if(SiS_BridgeInSlavemode(SiS_Pr)) {
                       tempbx |= SetSimuScanMode;
-                   }
-                 }
-              }
-          }
-       }
-
-       if(!(tempbx & DisableCRT2Display)) {
-           if(tempbx & DriverMode) {
-              if(tempbx & SetSimuScanMode) {
-                if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
-                   if( (HwInfo->jChipType >= SIS_315H) &&
-                       (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) ) {
-                      if(resinfo != SIS_RI_1600x1200) {
-                         tempbx |= SetInSlaveMode;
-                      }
-                   } else {
-                      tempbx |= SetInSlaveMode;
-                    }
-                }
-              }
-           } else {
-              tempbx |= SetInSlaveMode;
-          }
-       }
+                   }
+                }
+             }
+          }
+       }
 
-  }
+       if(!(tempbx & DisableCRT2Display)) {
+          if(tempbx & DriverMode) {
+             if(tempbx & SetSimuScanMode) {
+                if((!(modeflag & CRT2Mode)) && (checkcrt2mode)) {
+                   if(resinfo != SIS_RI_1600x1200) {
+                      tempbx |= SetInSlaveMode;
+                   }
+                }
+             }
+          } else {
+             tempbx |= SetInSlaveMode;
+          }
+       }
 
-  SiS_Pr->SiS_VBInfo = tempbx;
+   }
 
-  if(HwInfo->jChipType == SIS_630) {
-     SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
-  }
+   SiS_Pr->SiS_VBInfo = tempbx;
 
-#ifdef TWDEBUG
-#ifdef LINUX_KERNEL
-  printk(KERN_DEBUG "sisfb: (VBInfo= 0x%04x, SetFlag=0x%04x)\n",
+#ifdef SIS300
+   if(SiS_Pr->ChipType == SIS_630) {
+      SiS_SetChrontelGPIO(SiS_Pr, SiS_Pr->SiS_VBInfo);
+   }
+#endif
+
+#ifdef SIS_LINUX_KERNEL
+#if 0
+   printk(KERN_DEBUG "sisfb: (init301: VBInfo= 0x%04x, SetFlag=0x%04x)\n",
       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
 #endif
-#ifdef LINUX_XF86
-  xf86DrvMsgVerb(0, X_PROBED, 3, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
+#endif
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_PROBED, "(init301: VBInfo=0x%04x, SetFlag=0x%04x)\n",
       SiS_Pr->SiS_VBInfo, SiS_Pr->SiS_SetFlag);
 #endif
 #endif
@@ -1212,41 +1182,41 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 void
-SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SetYPbPr(struct SiS_Private *SiS_Pr)
 {
 
-  UCHAR temp;
+   unsigned char temp;
 
-  /* Note: This variable is only used on 30xLV systems.
-   * CR38 has a different meaning on LVDS/CH7019 systems.
-   * On 661 and later, these bits moved to CR35.
-   *
-   * On 301, 301B, only HiVision 1080i is supported.
-   * On 30xLV, 301C, only YPbPr 1080i is supported.
-   */
+   /* Note: This variable is only used on 30xLV systems.
+    * CR38 has a different meaning on LVDS/CH7019 systems.
+    * On 661 and later, these bits moved to CR35.
+    *
+    * On 301, 301B, only HiVision 1080i is supported.
+    * On 30xLV, 301C, only YPbPr 1080i is supported.
+    */
 
-  SiS_Pr->SiS_YPbPr = 0;
-  if(HwInfo->jChipType >= SIS_661) return;
+   SiS_Pr->SiS_YPbPr = 0;
+   if(SiS_Pr->ChipType >= SIS_661) return;
 
-  if(SiS_Pr->SiS_VBType) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-       SiS_Pr->SiS_YPbPr = YPbPrHiVision;
-     }
-  }
+   if(SiS_Pr->SiS_VBType) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+        SiS_Pr->SiS_YPbPr = YPbPrHiVision;
+      }
+   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_SIS301C)) {
-        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-       if(temp & 0x08) {
-          switch((temp >> 4)) {
-          case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
-          case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
-          case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
-          case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
-          }
-       }
-     }
-  }
+   if(SiS_Pr->ChipType >= SIS_315H) {
+      if(SiS_Pr->SiS_VBType & VB_SISYPBPR) {
+        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+        if(temp & 0x08) {
+           switch((temp >> 4)) {
+           case 0x00: SiS_Pr->SiS_YPbPr = YPbPr525i;     break;
+           case 0x01: SiS_Pr->SiS_YPbPr = YPbPr525p;     break;
+           case 0x02: SiS_Pr->SiS_YPbPr = YPbPr750p;     break;
+           case 0x03: SiS_Pr->SiS_YPbPr = YPbPrHiVision; break;
+           }
+        }
+      }
+   }
 
 }
 
@@ -1255,199 +1225,204 @@ SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 void
-SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo)
+SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT temp, temp1, resinfo = 0, romindex = 0;
-  UCHAR  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short temp, temp1, resinfo = 0, romindex = 0;
+   unsigned char  OutputSelect = *SiS_Pr->pSiS_OutputSelect;
 
-  SiS_Pr->SiS_TVMode = 0;
+   SiS_Pr->SiS_TVMode = 0;
 
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
-  if(SiS_Pr->UseCustomMode) return;
+   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
+   if(SiS_Pr->UseCustomMode) return;
 
-  if(ModeNo > 0x13) {
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
-  }
+   if(ModeNo > 0x13) {
+      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+   }
 
-  if(HwInfo->jChipType < SIS_661) {
+   if(SiS_Pr->ChipType < SIS_661) {
 
-     if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
+      if(SiS_Pr->SiS_VBInfo & SetPALTV) SiS_Pr->SiS_TVMode |= TVSetPAL;
 
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        temp = 0;
-        if((HwInfo->jChipType == SIS_630) ||
-           (HwInfo->jChipType == SIS_730)) {
-           temp = 0x35;
-          romindex = 0xfe;
-        } else if(HwInfo->jChipType >= SIS_315H) {
-           temp = 0x38;
-          romindex = 0xf3;
-          if(HwInfo->jChipType >= SIS_330) romindex = 0x11b;
-        }
-        if(temp) {
-           if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
-             OutputSelect = ROMAddr[romindex];
-             if(!(OutputSelect & EnablePALMN)) {
-                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
-             }
-          }
-          temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
-          if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-              if(temp1 & EnablePALM) {         /* 0x40 */
-                 SiS_Pr->SiS_TVMode |= TVSetPALM;
-                SiS_Pr->SiS_TVMode &= ~TVSetPAL;
-             } else if(temp1 & EnablePALN) {   /* 0x80 */
-                SiS_Pr->SiS_TVMode |= TVSetPALN;
-              }
-          } else {
-              if(temp1 & EnableNTSCJ) {                /* 0x40 */
-                SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
-             }
-          }
-        }
-       /* Translate HiVision/YPbPr to our new flags */
-       if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-          if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
-          else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
-          else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
-          else                                        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
-          if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
-             SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
-             SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
-          } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
-             SiS_Pr->SiS_TVMode |= TVSetPAL;
-          }
-       }
-     } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-        if(SiS_Pr->SiS_CHOverScan) {
-           if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-              if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
-                SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-              }
-           } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-             temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
-             if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
-                SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-             }
-          }
-           if(SiS_Pr->SiS_CHSOverScan) {
-              SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-           }
-        }
-        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-          temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
-          if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-              if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
-             else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
-           } else {
-             if(temp & EnableNTSCJ) {
-                SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
-             }
-          }
-       }
-     }
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        temp = 0;
+        if((SiS_Pr->ChipType == SIS_630) ||
+           (SiS_Pr->ChipType == SIS_730)) {
+           temp = 0x35;
+           romindex = 0xfe;
+        } else if(SiS_Pr->ChipType >= SIS_315H) {
+           temp = 0x38;
+           if(SiS_Pr->ChipType < XGI_20) {
+              romindex = 0xf3;
+              if(SiS_Pr->ChipType >= SIS_330) romindex = 0x11b;
+           }
+        }
+        if(temp) {
+           if(romindex && SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
+              OutputSelect = ROMAddr[romindex];
+              if(!(OutputSelect & EnablePALMN)) {
+                 SiS_SetRegAND(SiS_Pr->SiS_P3d4,temp,0x3F);
+              }
+           }
+           temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,temp);
+           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+              if(temp1 & EnablePALM) {         /* 0x40 */
+                 SiS_Pr->SiS_TVMode |= TVSetPALM;
+                 SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+              } else if(temp1 & EnablePALN) {  /* 0x80 */
+                 SiS_Pr->SiS_TVMode |= TVSetPALN;
+              }
+           } else {
+              if(temp1 & EnableNTSCJ) {        /* 0x40 */
+                 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+              }
+           }
+        }
+        /* Translate HiVision/YPbPr to our new flags */
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+           if(SiS_Pr->SiS_YPbPr == YPbPr750p)          SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+           else if(SiS_Pr->SiS_YPbPr == YPbPr525p)     SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+           else if(SiS_Pr->SiS_YPbPr == YPbPrHiVision) SiS_Pr->SiS_TVMode |= TVSetHiVision;
+           else                                        SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+           if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p | TVSetYPbPr525i)) {
+              SiS_Pr->SiS_VBInfo &= ~SetCRT2ToHiVision;
+              SiS_Pr->SiS_VBInfo |= SetCRT2ToYPbPr525750;
+           } else if(SiS_Pr->SiS_TVMode & TVSetHiVision) {
+              SiS_Pr->SiS_TVMode |= TVSetPAL;
+           }
+        }
+      } else if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+        if(SiS_Pr->SiS_CHOverScan) {
+           if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+              if((temp & TVOverScan) || (SiS_Pr->SiS_CHOverScan == 1)) {
+                 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+              }
+           } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+              temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
+              if((temp & 0x80) || (SiS_Pr->SiS_CHOverScan == 1)) {
+                 SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+              }
+           }
+           if(SiS_Pr->SiS_CHSOverScan) {
+              SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+           }
+        }
+        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+           temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x38);
+           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+              if(temp & EnablePALM)      SiS_Pr->SiS_TVMode |= TVSetPALM;
+              else if(temp & EnablePALN) SiS_Pr->SiS_TVMode |= TVSetPALN;
+           } else {
+              if(temp & EnableNTSCJ) {
+                 SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+              }
+           }
+        }
+      }
 
-  } else {  /* 661 and later */
+   } else {  /* 661 and later */
 
-     temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-     if(temp1 & 0x01) {
-        SiS_Pr->SiS_TVMode |= TVSetPAL;
-       if(temp1 & 0x08) {
-          SiS_Pr->SiS_TVMode |= TVSetPALN;
-       } else if(temp1 & 0x04) {
-          if(SiS_Pr->SiS_VBType & VB_SISVB) {
-             SiS_Pr->SiS_TVMode &= ~TVSetPAL;
-          }
-          SiS_Pr->SiS_TVMode |= TVSetPALM;
-       }
-     } else {
-        if(temp1 & 0x02) {
-          SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
-       }
-     }
-     if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-        if(SiS_Pr->SiS_CHOverScan) {
-           if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
-             SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
-          }
-       }
-     }
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-          temp1 &= 0xe0;
-          if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
-          else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
-          else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
-       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-          SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
-       }
-       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
-          if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
-             SiS_Pr->SiS_TVMode |= TVAspect169;
-          } else {
-             temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
-             if(temp1 & 0x02) {
-                if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
-                   SiS_Pr->SiS_TVMode |= TVAspect169;
-                } else {
-                   SiS_Pr->SiS_TVMode |= TVAspect43LB;
-                }
-             } else {
-                SiS_Pr->SiS_TVMode |= TVAspect43;
-             }
-          }
-       }
-     }
-  }
+      temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
+      if(temp1 & 0x01) {
+        SiS_Pr->SiS_TVMode |= TVSetPAL;
+        if(temp1 & 0x08) {
+           SiS_Pr->SiS_TVMode |= TVSetPALN;
+        } else if(temp1 & 0x04) {
+           if(SiS_Pr->SiS_VBType & VB_SISVB) {
+              SiS_Pr->SiS_TVMode &= ~TVSetPAL;
+           }
+           SiS_Pr->SiS_TVMode |= TVSetPALM;
+        }
+      } else {
+        if(temp1 & 0x02) {
+           SiS_Pr->SiS_TVMode |= TVSetNTSCJ;
+        }
+      }
+      if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+        if(SiS_Pr->SiS_CHOverScan) {
+           if((temp1 & 0x10) || (SiS_Pr->SiS_CHOverScan == 1)) {
+              SiS_Pr->SiS_TVMode |= TVSetCHOverScan;
+           }
+        }
+      }
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+           temp1 &= 0xe0;
+           if(temp1 == 0x00)      SiS_Pr->SiS_TVMode |= TVSetYPbPr525i;
+           else if(temp1 == 0x20) SiS_Pr->SiS_TVMode |= TVSetYPbPr525p;
+           else if(temp1 == 0x40) SiS_Pr->SiS_TVMode |= TVSetYPbPr750p;
+        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+           SiS_Pr->SiS_TVMode |= (TVSetHiVision | TVSetPAL);
+        }
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToYPbPr525750 | SetCRT2ToHiVision)) {
+           if(resinfo == SIS_RI_800x480 || resinfo == SIS_RI_1024x576 || resinfo == SIS_RI_1280x720) {
+              SiS_Pr->SiS_TVMode |= TVAspect169;
+           } else {
+              temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x39);
+              if(temp1 & 0x02) {
+                 if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetHiVision)) {
+                    SiS_Pr->SiS_TVMode |= TVAspect169;
+                 } else {
+                    SiS_Pr->SiS_TVMode |= TVAspect43LB;
+                 }
+              } else {
+                 SiS_Pr->SiS_TVMode |= TVAspect43;
+              }
+           }
+        }
+      }
+   }
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToSCART) SiS_Pr->SiS_TVMode |= TVSetPAL;
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-        SiS_Pr->SiS_TVMode |= TVSetPAL;
-       SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
-     } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-        if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
-          SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
-       }
-     }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+        SiS_Pr->SiS_TVMode |= TVSetPAL;
+        SiS_Pr->SiS_TVMode &= ~(TVSetPALM | TVSetPALN | TVSetNTSCJ);
+      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+        if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525i | TVSetYPbPr525p | TVSetYPbPr750p)) {
+           SiS_Pr->SiS_TVMode &= ~(TVSetPAL | TVSetNTSCJ | TVSetPALM | TVSetPALN);
+        }
+      }
 
-     if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-           SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
-        }
-     }
+      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+        if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+           SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+        }
+      }
 
-     if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-        /* BIOS sets TVNTSC1024 without checking 525p here. Wrong? */
-        if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr525p | TVSetYPbPr750p))) {
-           if(resinfo == SIS_RI_1024x768) {
-              SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
-          }
-        }
-     }
+      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+        if(resinfo == SIS_RI_1024x768) {
+           if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
+              SiS_Pr->SiS_TVMode |= TVSet525p1024;
+           } else if(!(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p))) {
+              SiS_Pr->SiS_TVMode |= TVSetNTSC1024;
+           }
+        }
+      }
 
-     SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
-     if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
-        (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-       SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
-     } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
-        SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
-     } else if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
-        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-           SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
-        }
-     }
+      SiS_Pr->SiS_TVMode |= TVRPLLDIV2XO;
+      if((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) &&
+        (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+        SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+      } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+        SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+      } else if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) {
+        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+           SiS_Pr->SiS_TVMode &= ~TVRPLLDIV2XO;
+        }
+      }
 
-  }
+   }
 
-  SiS_Pr->SiS_VBInfo &= ~SetPALTV;
+   SiS_Pr->SiS_VBInfo &= ~SetPALTV;
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
-  xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
+   xf86DrvMsg(0, X_INFO, "(init301: TVMode %x, VBInfo %x)\n", SiS_Pr->SiS_TVMode, SiS_Pr->SiS_VBInfo);
+#endif
 #endif
 }
 
@@ -1455,41 +1430,46 @@ SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_IN
 /*               GET LCD INFO                */
 /*********************************************/
 
-static USHORT
-SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_GetBIOSLCDResInfo(struct SiS_Private *SiS_Pr)
 {
-   USHORT temp = SiS_Pr->SiS_LCDResInfo;
+   unsigned short temp = SiS_Pr->SiS_LCDResInfo;
    /* Translate my LCDResInfo to BIOS value */
-   if(temp == Panel_1280x768_2)  temp = Panel_1280x768;
-   if(temp == Panel_1280x800_2)  temp = Panel_1280x800;
+   switch(temp) {
+   case Panel_1280x768_2: temp = Panel_1280x768;    break;
+   case Panel_1280x800_2: temp = Panel_1280x800;    break;
+   case Panel_1280x854:   temp = Panel661_1280x854; break;
+   }
    return temp;
 }
 
 static void
-SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_GetLCDInfoBIOS(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
-   UCHAR  *ROMAddr;
-   USHORT temp;
+   unsigned char  *ROMAddr;
+   unsigned short temp;
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
    xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
-       SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+       SiS_Pr->PanelHT, SiS_Pr->PanelVT,
        SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
        SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
        SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
        SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
        SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif
 #endif
 
-   if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+   if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
       if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
-         SiS_Pr->SiS_NeedRomModeData = TRUE;
+        SiS_Pr->SiS_NeedRomModeData = TRUE;
         SiS_Pr->PanelHT  = temp;
       }
       if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
-         SiS_Pr->SiS_NeedRomModeData = TRUE;
-         SiS_Pr->PanelVT  = temp;
+        SiS_Pr->SiS_NeedRomModeData = TRUE;
+        SiS_Pr->PanelVT  = temp;
       }
       SiS_Pr->PanelHRS = SISGETROMW(10);
       SiS_Pr->PanelHRE = SISGETROMW(12);
@@ -1497,20 +1477,22 @@ SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
       SiS_Pr->PanelVRE = SISGETROMW(16);
       SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
-        SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
+        SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (unsigned short)((unsigned char)ROMAddr[18]);
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
         SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
       xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
-       SiS_Pr->PanelHT, SiS_Pr->PanelVT,
+       SiS_Pr->PanelHT, SiS_Pr->PanelVT,
        SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
        SiS_Pr->PanelVRS, SiS_Pr->PanelVRE,
        SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
        SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A,
        SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif
 #endif
 
    }
@@ -1518,35 +1500,35 @@ SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 }
 
 static void
-SiS_CheckScaling(SiS_Private *SiS_Pr, USHORT resinfo, const UCHAR *nonscalingmodes)
-{
-    int i = 0;
-    while(nonscalingmodes[i] != 0xff) {
-        if(nonscalingmodes[i++] == resinfo) {
-          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
-             (SiS_Pr->UsePanelScaler == -1)) {
-             SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-          }
-          break;
-       }
-    }
+SiS_CheckScaling(struct SiS_Private *SiS_Pr, unsigned short resinfo,
+                       const unsigned char *nonscalingmodes)
+{
+   int i = 0;
+   while(nonscalingmodes[i] != 0xff) {
+      if(nonscalingmodes[i++] == resinfo) {
+        if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) ||
+           (SiS_Pr->UsePanelScaler == -1)) {
+           SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+        }
+        break;
+      }
+   }
 }
 
 void
-SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                 PSIS_HW_INFO HwInfo)
+SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
+  unsigned short temp,modeflag,resinfo=0,modexres=0,modeyres=0;
+  BOOLEAN panelcanscale = FALSE;
 #ifdef SIS300
-  UCHAR *ROMAddr = HwInfo->pjVirtualRomBase;
-  const unsigned char SiS300SeriesLCDRes[] =
+  unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+  static const unsigned char SiS300SeriesLCDRes[] =
           { 0,  1,  2,  3,  7,  4,  5,  8,
            0,  0, 10,  0,  0,  0,  0, 15 };
 #endif
 #ifdef SIS315H
-  UCHAR   *myptr = NULL;
+  unsigned char   *myptr = NULL;
 #endif
-  USHORT  temp,modeflag,resinfo=0,modexres=0,modeyres=0;
-  BOOLEAN panelcanscale = FALSE;
 
   SiS_Pr->SiS_LCDResInfo  = 0;
   SiS_Pr->SiS_LCDTypeInfo = 0;
@@ -1557,14 +1539,14 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   SiS_Pr->PanelVRE        = 999; /* VSync end */
   SiS_Pr->SiS_NeedRomModeData = FALSE;
 
+  /* Alternative 1600x1200@60 timing for 1600x1200 LCDA */
+  SiS_Pr->Alternate1600x1200 = FALSE;
+
   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
+
+  if((ModeNo > 0x13) && (!SiS_Pr->UseCustomMode)) {
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      modexres = SiS_Pr->SiS_ModeResInfo[resinfo].HTotal;
      modeyres = SiS_Pr->SiS_ModeResInfo[resinfo].VTotal;
@@ -1575,16 +1557,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   /* For broken BIOSes: Assume 1024x768 */
   if(temp == 0) temp = 0x02;
 
-  if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+  if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
      SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
-  } else if((HwInfo->jChipType < SIS_315H) || (HwInfo->jChipType >= SIS_661)) {
+  } else if((SiS_Pr->ChipType < SIS_315H) || (SiS_Pr->ChipType >= SIS_661)) {
      SiS_Pr->SiS_LCDTypeInfo = temp >> 4;
   } else {
      SiS_Pr->SiS_LCDTypeInfo = (temp & 0x0F) - 1;
   }
   temp &= 0x0f;
 #ifdef SIS300
-  if(HwInfo->jChipType < SIS_315H) {
+  if(SiS_Pr->ChipType < SIS_315H) {
      /* Very old BIOSes only know 7 sizes (NetVista 2179, 1.01g) */
      if(SiS_Pr->SiS_VBType & VB_SIS301) {
         if(temp < 0x0f) temp &= 0x07;
@@ -1595,17 +1577,22 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 #endif
 
   /* Translate to our internal types */
-  if(HwInfo->jChipType == SIS_550) {
-     if(temp == Panel310_640x480_2) temp = Panel_640x480_2;
-     if(temp == Panel310_640x480_3) temp = Panel_640x480_3;
+#ifdef SIS315H
+  if(SiS_Pr->ChipType == SIS_550) {
+     if     (temp == Panel310_1152x768)  temp = Panel_320x240_2; /* Verified working */
+     else if(temp == Panel310_320x240_2) temp = Panel_320x240_2;
+     else if(temp == Panel310_320x240_3) temp = Panel_320x240_3;
+  } else if(SiS_Pr->ChipType >= SIS_661) {
+     if(temp == Panel661_1280x854)       temp = Panel_1280x854;
   }
+#endif
 
-  if(SiS_Pr->SiS_VBType & VB_SISLVDS) {        /* SiS LVDS */
+  if(SiS_Pr->SiS_VBType & VB_SISLVDS) {                /* SiS LVDS */
      if(temp == Panel310_1280x768) {
         temp = Panel_1280x768_2;
      }
      if(SiS_Pr->SiS_ROMNew) {
-        if(temp == Panel661_1280x800) {
+       if(temp == Panel661_1280x800) {
           temp = Panel_1280x800_2;
        }
      }
@@ -1613,13 +1600,17 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   SiS_Pr->SiS_LCDResInfo = temp;
 
+#ifdef SIS300
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
      if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-        SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
+       SiS_Pr->SiS_LCDResInfo = Panel_Barco1366;
      } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-        SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+       SiS_Pr->SiS_LCDResInfo = Panel_848x480;
+     } else if(SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+       SiS_Pr->SiS_LCDResInfo = Panel_856x480;
      }
   }
+#endif
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_LCDResInfo < SiS_Pr->SiS_PanelMin301)
@@ -1633,10 +1624,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   SiS_Pr->SiS_LCDInfo = temp & ~0x000e;
   /* Need temp below! */
 
-  /* These can't scale no matter what */
+  /* These must/can't scale no matter what */
   switch(SiS_Pr->SiS_LCDResInfo) {
+  case Panel_320x240_1:
+  case Panel_320x240_2:
+  case Panel_320x240_3:
   case Panel_1280x960:
       SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
+      break;
+  case Panel_640x480:
+      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
   }
 
   panelcanscale = (SiS_Pr->SiS_LCDInfo & DontExpandLCD) ? TRUE : FALSE;
@@ -1646,41 +1643,41 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   /* Dual link, Pass 1:1 BIOS default, etc. */
 #ifdef SIS315H
-  if(HwInfo->jChipType >= SIS_661) {
+  if(SiS_Pr->ChipType >= SIS_661) {
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+       if(temp & 0x08) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
-     if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-        if(SiS_Pr->SiS_ROMNew) {
+     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+       if(SiS_Pr->SiS_ROMNew) {
           if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
-       } else if((myptr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
-           if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
+       } else if((myptr = GetLCDStructPtr661(SiS_Pr))) {
+          if(myptr[2] & 0x01) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
        }
      }
-  } else if(HwInfo->jChipType >= SIS_315H) {
+  } else if(SiS_Pr->ChipType >= SIS_315H) {
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
+       if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x01) SiS_Pr->SiS_LCDInfo |= LCDPass11;
      }
      if((SiS_Pr->SiS_ROMNew) && (!(SiS_Pr->PanelSelfDetected))) {
-        SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
+       SiS_Pr->SiS_LCDInfo &= ~(LCDRGB18Bit);
        temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x35);
-        if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
-       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+       if(temp & 0x01) SiS_Pr->SiS_LCDInfo |= LCDRGB18Bit;
+       if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
           if(temp & 0x02) SiS_Pr->SiS_LCDInfo |= LCDDualLink;
        }
      } else if(!(SiS_Pr->SiS_ROMNew)) {
-        if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-           if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
+       if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+          if((SiS_Pr->SiS_CustomT == CUT_CLEVO1024) &&
              (SiS_Pr->SiS_LCDResInfo == Panel_1024x768)) {
              SiS_Pr->SiS_LCDInfo |= LCDDualLink;
           }
-           if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
+          if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
              (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
-              (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
+             (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
              (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
              SiS_Pr->SiS_LCDInfo |= LCDDualLink;
           }
-        }
+       }
      }
   }
 #endif
@@ -1691,12 +1688,12 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
-        /* Always center screen on SiS LVDS (if scaling is disabled) */
-        SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+       /* Always center screen on SiS LVDS (if scaling is disabled) */
+       SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
      } else {
-        /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
-        if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
-        if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+       /* By default, pass 1:1 on SiS TMDS (if scaling is supported) */
+       if(panelcanscale)             SiS_Pr->SiS_LCDInfo |= LCDPass11;
+       if(SiS_Pr->CenterScreen == 1) SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
      }
   }
 
@@ -1704,19 +1701,15 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
 
   switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_320x480:    SiS_Pr->PanelXRes =  320; SiS_Pr->PanelYRes =  480;
-                           SiS_Pr->PanelHT   =  400; SiS_Pr->PanelVT   =  525;
-                           SiS_Pr->PanelVCLKIdx300 = VCLK28;
-                           SiS_Pr->PanelVCLKIdx315 = VCLK28;
-                           break;
-     case Panel_640x480_2:
-     case Panel_640x480_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
-                           SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
+     case Panel_320x240_1:
+     case Panel_320x240_2:
+     case Panel_320x240_3:  SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
+                           SiS_Pr->PanelVRS  =   24; SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx300 = VCLK28;
                            SiS_Pr->PanelVCLKIdx315 = VCLK28;
                            break;
      case Panel_640x480:    SiS_Pr->PanelXRes =  640; SiS_Pr->PanelYRes =  480;
-                                                     SiS_Pr->PanelVRE  =    3;
+                                                     SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx300 = VCLK28;
                            SiS_Pr->PanelVCLKIdx315 = VCLK28;
                            break;
@@ -1728,52 +1721,52 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                            SiS_Pr->PanelVCLKIdx315 = VCLK40;
                            break;
      case Panel_1024x600:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  600;
-                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
+                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  800;
                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
                            SiS_Pr->PanelVRS  =    2 /* 88 */ ; SiS_Pr->PanelVRE  =    6;
-                           SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+                           SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
-                           break;
+                           break;
      case Panel_1024x768:   SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
-                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
                            SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-                           if(HwInfo->jChipType < SIS_315H) {
+                           if(SiS_Pr->ChipType < SIS_315H) {
                               SiS_Pr->PanelHRS = 23;
-                                                     SiS_Pr->PanelVRE  =    5;
+                                                     SiS_Pr->PanelVRE  =    5;
                            }
                            SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1152x768:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  768;
-                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
-                           SiS_Pr->PanelHRS  =   24;
+                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+                           SiS_Pr->PanelHRS  =   24; SiS_Pr->PanelHRE  =  136;
                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
-                           if(HwInfo->jChipType < SIS_315H) {
+                           if(SiS_Pr->ChipType < SIS_315H) {
                               SiS_Pr->PanelHRS = 23;
-                                                     SiS_Pr->PanelVRE  =    5;
+                                                     SiS_Pr->PanelVRE  =    5;
                            }
-                           SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
+                           SiS_Pr->PanelVCLKIdx300 = VCLK65_300;
                            SiS_Pr->PanelVCLKIdx315 = VCLK65_315;
-                           break;
+                           break;
      case Panel_1152x864:   SiS_Pr->PanelXRes = 1152; SiS_Pr->PanelYRes =  864;
-                           break;
+                           break;
      case Panel_1280x720:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  720;
-                           SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
+                           SiS_Pr->PanelHT   = 1650; SiS_Pr->PanelVT   =  750;
                            SiS_Pr->PanelHRS  =  110; SiS_Pr->PanelHRE  =   40;
                            SiS_Pr->PanelVRS  =    5; SiS_Pr->PanelVRE  =    5;
                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x720;
                            /* Data above for TMDS (projector); get from BIOS for LVDS */
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1280x768:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
-                           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+                           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
                               SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  806;
                               SiS_Pr->PanelVCLKIdx300 = VCLK81_300; /* ? */
                               SiS_Pr->PanelVCLKIdx315 = VCLK81_315; /* ? */
                            } else {
-                              SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
+                              SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   =  802;
                               SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRS  =  112;
                               SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
                               SiS_Pr->PanelVCLKIdx300 = VCLK81_300;
@@ -1781,77 +1774,100 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                            }
                            break;
      case Panel_1280x768_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  768;
-                           SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
+                           SiS_Pr->PanelHT   = 1660; SiS_Pr->PanelVT   =  806;
                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x768_2;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
-                           SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
+                           SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
                            SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
                            SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1280x800_2: SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
-                           SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
+                           SiS_Pr->PanelHT   = 1552; SiS_Pr->PanelVT   =  812;
                            SiS_Pr->PanelHRS   =  48; SiS_Pr->PanelHRE  =  112;
                            SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx315 = VCLK_1280x800_315_2;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
+                           break;
+     case Panel_1280x854:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  854;
+                           SiS_Pr->PanelHT   = 1664; SiS_Pr->PanelVT   =  861;
+                           SiS_Pr->PanelHRS   =  16; SiS_Pr->PanelHRE  =  112;
+                           SiS_Pr->PanelVRS   =   1; SiS_Pr->PanelVRE  =    3;
+                           SiS_Pr->PanelVCLKIdx315 = VCLK_1280x854;
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
-                           SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
+                           SiS_Pr->PanelHT   = 1800; SiS_Pr->PanelVT   = 1000;
                            SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
                            SiS_Pr->PanelVCLKIdx315 = VCLK108_3_315;
-                           if(resinfo == SIS_RI_1280x1024) {
+                           if(resinfo == SIS_RI_1280x1024) {
                               SiS_Pr->PanelVCLKIdx300 = VCLK100_300;
                               SiS_Pr->PanelVCLKIdx315 = VCLK100_315;
                            }
                            break;
      case Panel_1280x1024:  SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes = 1024;
-                           SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+                           SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
                            SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx300 = VCLK108_3_300;
                            SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1400x1050:  SiS_Pr->PanelXRes = 1400; SiS_Pr->PanelYRes = 1050;
-                           SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
-                           SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112; /* HRE OK for LVDS, not for LCDA */
+                           SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+                           SiS_Pr->PanelHRS  =   48; SiS_Pr->PanelHRE  =  112;
                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx315 = VCLK108_2_315;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1600x1200:  SiS_Pr->PanelXRes = 1600; SiS_Pr->PanelYRes = 1200;
-                           SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
+                           SiS_Pr->PanelHT   = 2160; SiS_Pr->PanelVT   = 1250;
                            SiS_Pr->PanelHRS  =   64; SiS_Pr->PanelHRE  =  192;
                            SiS_Pr->PanelVRS  =    1; SiS_Pr->PanelVRE  =    3;
                            SiS_Pr->PanelVCLKIdx315 = VCLK162_315;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           if(SiS_Pr->SiS_VBType & VB_SISTMDSLCDA) {
+                              if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+                                 SiS_Pr->PanelHT  = 1760; SiS_Pr->PanelVT  = 1235;
+                                 SiS_Pr->PanelHRS =   48; SiS_Pr->PanelHRE =   32;
+                                 SiS_Pr->PanelVRS =    2; SiS_Pr->PanelVRE =    4;
+                                 SiS_Pr->PanelVCLKIdx315 = VCLK130_315;
+                                 SiS_Pr->Alternate1600x1200 = TRUE;
+                              }
+                           } else if(SiS_Pr->SiS_IF_DEF_LVDS) {
+                              SiS_Pr->PanelHT  = 2048; SiS_Pr->PanelVT  = 1320;
+                              SiS_Pr->PanelHRS = SiS_Pr->PanelHRE = 999;
+                              SiS_Pr->PanelVRS = SiS_Pr->PanelVRE = 999;
+                           }
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_1680x1050:  SiS_Pr->PanelXRes = 1680; SiS_Pr->PanelYRes = 1050;
-                           SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
+                           SiS_Pr->PanelHT   = 1900; SiS_Pr->PanelVT   = 1066;
                            SiS_Pr->PanelHRS  =   26; SiS_Pr->PanelHRE  =   76;
                            SiS_Pr->PanelVRS  =    3; SiS_Pr->PanelVRE  =    6;
                            SiS_Pr->PanelVCLKIdx315 = VCLK121_315;
-                           SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
+                           SiS_GetLCDInfoBIOS(SiS_Pr);
                            break;
      case Panel_Barco1366:  SiS_Pr->PanelXRes = 1360; SiS_Pr->PanelYRes = 1024;
-                           SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
-                           break;
+                           SiS_Pr->PanelHT   = 1688; SiS_Pr->PanelVT   = 1066;
+                           break;
      case Panel_848x480:    SiS_Pr->PanelXRes =  848; SiS_Pr->PanelYRes =  480;
-                           SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
-                           break;
+                           SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+                           break;
+     case Panel_856x480:    SiS_Pr->PanelXRes =  856; SiS_Pr->PanelYRes =  480;
+                           SiS_Pr->PanelHT   = 1088; SiS_Pr->PanelVT   =  525;
+                           break;
      case Panel_Custom:     SiS_Pr->PanelXRes = SiS_Pr->CP_MaxX;
-                           SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
+                           SiS_Pr->PanelYRes = SiS_Pr->CP_MaxY;
                            SiS_Pr->PanelHT   = SiS_Pr->CHTotal;
                            SiS_Pr->PanelVT   = SiS_Pr->CVTotal;
                            if(SiS_Pr->CP_PreferredIndex != -1) {
                               SiS_Pr->PanelXRes = SiS_Pr->CP_HDisplay[SiS_Pr->CP_PreferredIndex];
-                              SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
+                              SiS_Pr->PanelYRes = SiS_Pr->CP_VDisplay[SiS_Pr->CP_PreferredIndex];
                               SiS_Pr->PanelHT   = SiS_Pr->CP_HTotal[SiS_Pr->CP_PreferredIndex];
                               SiS_Pr->PanelVT   = SiS_Pr->CP_VTotal[SiS_Pr->CP_PreferredIndex];
                               SiS_Pr->PanelHRS  = SiS_Pr->CP_HSyncStart[SiS_Pr->CP_PreferredIndex];
@@ -1863,22 +1879,22 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                               SiS_Pr->PanelVRS -= SiS_Pr->PanelYRes;
                               SiS_Pr->PanelVRE -= SiS_Pr->PanelVRS;
                               if(SiS_Pr->CP_PrefClock) {
-                                 int idx;
-                                 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
+                                 int idx;
+                                 SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
                                  SiS_Pr->PanelVCLKIdx300 = VCLK_CUSTOM_300;
-                                 if(HwInfo->jChipType < SIS_315H) idx = VCLK_CUSTOM_300;
+                                 if(SiS_Pr->ChipType < SIS_315H) idx = VCLK_CUSTOM_300;
                                  else                             idx = VCLK_CUSTOM_315;
-                                 SiS_Pr->SiS_VCLKData[idx].CLOCK =
-                                    SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
-                                 SiS_Pr->SiS_VCLKData[idx].SR2B =
-                                    SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
-                                 SiS_Pr->SiS_VCLKData[idx].SR2C =
-                                    SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
+                                 SiS_Pr->SiS_VCLKData[idx].CLOCK =
+                                    SiS_Pr->SiS_VBVCLKData[idx].CLOCK = SiS_Pr->CP_PrefClock;
+                                 SiS_Pr->SiS_VCLKData[idx].SR2B =
+                                    SiS_Pr->SiS_VBVCLKData[idx].Part4_A = SiS_Pr->CP_PrefSR2B;
+                                 SiS_Pr->SiS_VCLKData[idx].SR2C =
+                                    SiS_Pr->SiS_VBVCLKData[idx].Part4_B = SiS_Pr->CP_PrefSR2C;
                               }
                            }
                            break;
      default:              SiS_Pr->PanelXRes = 1024; SiS_Pr->PanelYRes =  768;
-                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
+                           SiS_Pr->PanelHT   = 1344; SiS_Pr->PanelVT   =  806;
                            break;
   }
 
@@ -1887,14 +1903,16 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
       (SiS_Pr->SiS_IF_DEF_DSTN)              ||
       (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
       (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
      SiS_Pr->PanelHRS = 999;
      SiS_Pr->PanelHRE = 999;
   }
 
   if( (SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
       (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-      (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
+      (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
+      (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
      SiS_Pr->PanelVRS = 999;
      SiS_Pr->PanelVRE = 999;
   }
@@ -1912,18 +1930,18 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      case Panel_Custom:
      case Panel_1152x864:
      case Panel_1280x768:      /* TMDS only */
-        SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+       SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
        break;
 
      case Panel_800x600: {
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, 0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
        break;
      }
      case Panel_1024x768: {
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
           0xff
@@ -1932,7 +1950,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
        break;
      }
      case Panel_1280x720: {
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
           0xff
@@ -1944,7 +1962,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
        break;
      }
      case Panel_1280x768_2: {  /* LVDS only */
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
           SIS_RI_1152x768,0xff
@@ -1952,23 +1970,23 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
        switch(resinfo) {
        case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
-                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-                              }
-                              break;
+                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+                              }
+                              break;
        }
-        break;
+       break;
      }
      case Panel_1280x800: {    /* SiS TMDS special (Averatec 6200 series) */
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
           SIS_RI_1152x768,SIS_RI_1280x720,SIS_RI_1280x768,0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-        break;
+       break;
      }
      case Panel_1280x800_2:  {         /* SiS LVDS */
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
           SIS_RI_1152x768,0xff
@@ -1977,66 +1995,83 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
        switch(resinfo) {
        case SIS_RI_1280x720:
        case SIS_RI_1280x768:  if(SiS_Pr->UsePanelScaler == -1) {
-                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-                              }
-                              break;
+                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+                              }
+                              break;
        }
-        break;
+       break;
      }
-     case Panel_1280x960: {
-        static const UCHAR nonscalingmodes[] = {
+     case Panel_1280x854: {    /* SiS LVDS */
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-          SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
-          0xff
+          SIS_RI_1152x768,0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-        break;
-     }
-     case Panel_1280x1024: {
-        static const UCHAR nonscalingmodes[] = {
+       switch(resinfo) {
+       case SIS_RI_1280x720:
+       case SIS_RI_1280x768:
+       case SIS_RI_1280x800:  if(SiS_Pr->UsePanelScaler == -1) {
+                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+                              }
+                              break;
+       }
+       break;
+     }
+     case Panel_1280x960: {
+       static const unsigned char nonscalingmodes[] = {
+          SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
+          SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
+          SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
+          SIS_RI_1280x854,0xff
+       };
+       SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
+       break;
+     }
+     case Panel_1280x1024: {
+       static const unsigned char nonscalingmodes[] = {
           SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
           SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
           SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
-          SIS_RI_1280x960,0xff
+          SIS_RI_1280x854,SIS_RI_1280x960,0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
        break;
      }
      case Panel_1400x1050: {
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x960,
-            0xff
+            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x768,SIS_RI_1280x800,SIS_RI_1280x854,
+            SIS_RI_1280x960,0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-        switch(resinfo) {
+       switch(resinfo) {
        case SIS_RI_1280x720:  if(SiS_Pr->UsePanelScaler == -1) {
-                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-                              }
-                              break;
+                                 SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+                              }
+                              break;
        case SIS_RI_1280x1024: SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
-                              break;
+                              break;
        }
        break;
      }
      case Panel_1600x1200: {
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
             SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x720,SIS_RI_1280x768,SIS_RI_1280x800,
-            SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
+            SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
-        break;
+       break;
      }
      case Panel_1680x1050: {
-        static const UCHAR nonscalingmodes[] = {
+       static const unsigned char nonscalingmodes[] = {
             SIS_RI_720x480, SIS_RI_720x576, SIS_RI_768x576, SIS_RI_800x480, SIS_RI_848x480,
             SIS_RI_856x480, SIS_RI_960x540, SIS_RI_960x600, SIS_RI_1024x576,SIS_RI_1024x600,
-            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x960,SIS_RI_1360x768,SIS_RI_1360x1024,
-            0xff
+            SIS_RI_1152x768,SIS_RI_1152x864,SIS_RI_1280x854,SIS_RI_1280x960,SIS_RI_1360x768,
+            SIS_RI_1360x1024,0xff
        };
        SiS_CheckScaling(SiS_Pr, resinfo, nonscalingmodes);
        break;
@@ -2044,25 +2079,25 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      }
   }
 
+#ifdef SIS300
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-        SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
+     if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+       SiS_Pr->SiS_LCDInfo = 0x80 | 0x40 | 0x20;   /* neg h/v sync, RGB24(D0 = 0) */
      }
   }
 
-#ifdef SIS300
-  if(HwInfo->jChipType < SIS_315H) {
+  if(SiS_Pr->ChipType < SIS_315H) {
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        if(SiS_Pr->SiS_UseROM) {
+       if(SiS_Pr->SiS_UseROM) {
           if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-              if(!(ROMAddr[0x235] & 0x02)) {
-                SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
-             }
+             if(!(ROMAddr[0x235] & 0x02)) {
+                SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+             }
           }
-        }
-     } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+       }
+     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
        if((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10))) {
-           SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
+          SiS_Pr->SiS_LCDInfo &= (~DontExpandLCD);
        }
      }
   }
@@ -2080,7 +2115,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   switch(SiS_Pr->SiS_LCDResInfo) {
   case Panel_640x480:
-     SiS_Pr->SiS_LCDInfo |= LCDPass11;
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
      break;
   case Panel_1280x800:
      /* Don't pass 1:1 by default (TMDS special) */
@@ -2097,7 +2132,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      break;
   }
 
-  if(SiS_Pr->UseCustomMode) {
+  if((SiS_Pr->UseCustomMode) || (SiS_Pr->SiS_CustomT == CUT_UNKNOWNLCD)) {
      SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
   }
 
@@ -2107,19 +2142,19 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   }
 
   /* LVDS DDA */
-  if(!((HwInfo->jChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
+  if(!((SiS_Pr->ChipType < SIS_315H) && (SiS_Pr->SiS_SetFlag & SetDOSMode))) {
 
      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) || (SiS_Pr->SiS_VBType & VB_NoLCD)) {
        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 0) {
           if(ModeNo == 0x12) {
              if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-                SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+                SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
              }
           } else if(ModeNo > 0x13) {
              if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
-                if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-                   if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
-                       SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+                if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+                   if((resinfo == SIS_RI_800x600) || (resinfo == SIS_RI_400x300)) {
+                      SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
                    }
                 }
              }
@@ -2128,18 +2163,18 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      }
 
      if(modeflag & HalfDCLK) {
-        if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
+       if(SiS_Pr->SiS_IF_DEF_TRUMPION == 1) {
           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-        } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
        } else if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
           SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
        } else if(ModeNo > 0x13) {
-           if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-              if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-           } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
-              if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
-           }
+          if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+             if(resinfo == SIS_RI_512x384) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+          } else if(SiS_Pr->SiS_LCDResInfo == Panel_800x600) {
+             if(resinfo == SIS_RI_400x300) SiS_Pr->SiS_SetFlag |= EnableLVDSDDA;
+          }
        }
      }
 
@@ -2148,21 +2183,21 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   /* VESA timing */
   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
      if(SiS_Pr->SiS_VBInfo & SetNotSimuMode) {
-       SiS_Pr->SiS_SetFlag |= LCDVESATiming;
+       SiS_Pr->SiS_SetFlag |= LCDVESATiming;
      }
   } else {
      SiS_Pr->SiS_SetFlag |= LCDVESATiming;
   }
 
-#ifdef LINUX_KERNEL
-#ifdef TWDEBUG
+#ifdef SIS_LINUX_KERNEL
+#if 0
   printk(KERN_DEBUG "sisfb: (LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x)\n",
        SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo);
 #endif
 #endif
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
   xf86DrvMsgVerb(0, X_PROBED, 4,
-       "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
+       "(init301: LCDInfo=0x%04x LCDResInfo=0x%02x LCDTypeInfo=0x%02x SetFlag=0x%04x)\n",
        SiS_Pr->SiS_LCDInfo, SiS_Pr->SiS_LCDResInfo, SiS_Pr->SiS_LCDTypeInfo, SiS_Pr->SiS_SetFlag);
 #endif
 }
@@ -2171,45 +2206,46 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*                 GET VCLK                  */
 /*********************************************/
 
-USHORT
-SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+unsigned short
+SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
 {
-  USHORT CRT2Index,VCLKIndex=0,VCLKIndexGEN=0;
-  USHORT modeflag,resinfo,tempbx;
-  const UCHAR *CHTVVCLKPtr = NULL;
+  unsigned short CRT2Index, VCLKIndex = 0, VCLKIndexGEN = 0, VCLKIndexGENCRT = 0;
+  unsigned short modeflag, resinfo, tempbx;
+  const unsigned char *CHTVVCLKPtr = NULL;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
      resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
      CRT2Index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
      VCLKIndexGEN = (SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02)) >> 2) & 0x03;
+     VCLKIndexGENCRT = VCLKIndexGEN;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      CRT2Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
      VCLKIndexGEN = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-     if(HwInfo->jChipType < SIS_315H) VCLKIndexGEN &= 0x3f;
+     VCLKIndexGENCRT = SiS_GetRefCRTVCLK(SiS_Pr, RefreshRateTableIndex,
+               (SiS_Pr->SiS_SetFlag & ProgrammingCRT2) ? SiS_Pr->SiS_UseWideCRT2 : SiS_Pr->SiS_UseWide);
   }
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {    /* 30x/B/LV */
 
      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
-        CRT2Index >>= 6;
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {              /*  LCD */
+       CRT2Index >>= 6;
+       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {       /*  LCD */
 
-           if(HwInfo->jChipType < SIS_315H) {
+          if(SiS_Pr->ChipType < SIS_315H) {
              VCLKIndex = SiS_Pr->PanelVCLKIdx300;
              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-                VCLKIndex = VCLKIndexGEN;
+                VCLKIndex = VCLKIndexGEN;
              }
           } else {
              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
              if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
                 switch(resinfo) {
-                /* Only those whose IndexGEN doesn't match VBVCLK array */
-                case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
+                /* Correct those whose IndexGEN doesn't match VBVCLK array */
                 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
                 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
                 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
@@ -2218,18 +2254,19 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
                 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
                 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+                case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; break;
                 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
                 default:              VCLKIndex = VCLKIndexGEN;
                 }
 
                 if(ModeNo <= 0x13) {
-                   if(HwInfo->jChipType <= SIS_315PRO) {
+                   if(SiS_Pr->ChipType <= SIS_315PRO) {
                       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
-                   } else {
+                   } else {
                       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x00;
                    }
                 }
-                if(HwInfo->jChipType <= SIS_315PRO) {
+                if(SiS_Pr->ChipType <= SIS_315PRO) {
                    if(VCLKIndex == 0) VCLKIndex = 0x41;
                    if(VCLKIndex == 1) VCLKIndex = 0x43;
                    if(VCLKIndex == 4) VCLKIndex = 0x44;
@@ -2237,49 +2274,46 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
              }
           }
 
-        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                  /*  TV */
+       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                   /*  TV */
 
           if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-              if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)            VCLKIndex = HiTVVCLKDIV2;
-             else                                              VCLKIndex = HiTVVCLK;
-              if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-                if(modeflag & Charx8Dot)                       VCLKIndex = HiTVSimuVCLK;
-                else                                           VCLKIndex = HiTVTextVCLK;
-              }
-           } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      VCLKIndex = YPbPr750pVCLK;
-          else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)         VCLKIndex = TVVCLKDIV2;
-          else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)           VCLKIndex = TVVCLKDIV2;
-           else                                                VCLKIndex = TVVCLK;
-
-          if(HwInfo->jChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
-          else                             VCLKIndex += TVCLKBASE_315;
-
-        } else {                                                       /* VGA2 */
-
-          VCLKIndex = VCLKIndexGEN;
-          if(HwInfo->jChipType < SIS_315H) {
-              if(ModeNo > 0x13) {
-                if( (HwInfo->jChipType == SIS_630) &&
-                    (HwInfo->jChipRevision >= 0x30)) {
+             if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)        VCLKIndex = HiTVVCLKDIV2;
+             else                                         VCLKIndex = HiTVVCLK;
+             if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     VCLKIndex = HiTVSimuVCLK;
+          } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  VCLKIndex = YPbPr750pVCLK;
+          else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)    VCLKIndex = TVVCLKDIV2;
+          else if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO)      VCLKIndex = TVVCLKDIV2;
+          else                                            VCLKIndex = TVVCLK;
+
+          if(SiS_Pr->ChipType < SIS_315H) VCLKIndex += TVCLKBASE_300;
+          else                            VCLKIndex += TVCLKBASE_315;
+
+       } else {                                                        /* VGA2 */
+
+          VCLKIndex = VCLKIndexGENCRT;
+          if(SiS_Pr->ChipType < SIS_315H) {
+             if(ModeNo > 0x13) {
+                if( (SiS_Pr->ChipType == SIS_630) &&
+                    (SiS_Pr->ChipRevision >= 0x30)) {
                    if(VCLKIndex == 0x14) VCLKIndex = 0x34;
                 }
                 /* Better VGA2 clock for 1280x1024@75 */
                 if(VCLKIndex == 0x17) VCLKIndex = 0x45;
              }
-           }
-        }
+          }
+       }
 
      } else {   /* If not programming CRT2 */
 
-        VCLKIndex = VCLKIndexGEN;
-       if(HwInfo->jChipType < SIS_315H) {
-           if(ModeNo > 0x13) {
-             if( (HwInfo->jChipType != SIS_630) &&
-                 (HwInfo->jChipType != SIS_300) ) {
+       VCLKIndex = VCLKIndexGENCRT;
+       if(SiS_Pr->ChipType < SIS_315H) {
+          if(ModeNo > 0x13) {
+             if( (SiS_Pr->ChipType != SIS_630) &&
+                 (SiS_Pr->ChipType != SIS_300) ) {
                 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
              }
           }
-        }
+       }
      }
 
   } else {       /*   LVDS  */
@@ -2288,12 +2322,12 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
      if(SiS_Pr->SiS_SetFlag & ProgrammingCRT2) {
 
-        if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
+       if( (SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) ) {
 
           VCLKIndex &= 0x1f;
-           tempbx = 0;
+          tempbx = 0;
           if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-           if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+          if(SiS_Pr->SiS_TVMode & TVSetPAL) {
              tempbx += 2;
              if(SiS_Pr->SiS_ModeType > ModeVGA) {
                 if(SiS_Pr->SiS_CHSOverScan) tempbx = 8;
@@ -2306,66 +2340,68 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
                 if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
              }
           }
-                  switch(tempbx) {
-             case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
-             case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
-             case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
-             case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
+          switch(tempbx) {
+            case  0: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUNTSC;  break;
+            case  1: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKONTSC;  break;
+            case  2: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPAL;   break;
+            case  3: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
             case  4: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALM;  break;
-             case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
-             case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
-             case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
+            case  5: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALM;  break;
+            case  6: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKUPALN;  break;
+            case  7: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPALN;  break;
             case  8: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKSOPAL;  break;
             default: CHTVVCLKPtr = SiS_Pr->SiS_CHTVVCLKOPAL;   break;
-           }
-           VCLKIndex = CHTVVCLKPtr[VCLKIndex];
+          }
+          VCLKIndex = CHTVVCLKPtr[VCLKIndex];
 
-        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 
-          if(HwInfo->jChipType < SIS_315H) {
+          if(SiS_Pr->ChipType < SIS_315H) {
              VCLKIndex = SiS_Pr->PanelVCLKIdx300;
           } else {
              VCLKIndex = SiS_Pr->PanelVCLKIdx315;
           }
 
+#ifdef SIS300
           /* Special Timing: Barco iQ Pro R series */
           if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) VCLKIndex = 0x44;
 
-          /* Special Timing: 848x480 parallel lvds */
-          if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
-             if(HwInfo->jChipType < SIS_315H) {
+          /* Special Timing: 848x480 and 856x480 parallel lvds panels */
+          if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
+             if(SiS_Pr->ChipType < SIS_315H) {
                 VCLKIndex = VCLK34_300;
-                /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
+                /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
              } else {
                 VCLKIndex = VCLK34_315;
                 /* if(resinfo == SIS_RI_1360x768) VCLKIndex = ?; */
              }
           }
+#endif
 
-        } else {
+       } else {
 
-          VCLKIndex = VCLKIndexGEN;
-          if(HwInfo->jChipType < SIS_315H) {
-              if(ModeNo > 0x13) {
-                if( (HwInfo->jChipType == SIS_630) &&
-                     (HwInfo->jChipRevision >= 0x30) ) {
+          VCLKIndex = VCLKIndexGENCRT;
+          if(SiS_Pr->ChipType < SIS_315H) {
+             if(ModeNo > 0x13) {
+                if( (SiS_Pr->ChipType == SIS_630) &&
+                    (SiS_Pr->ChipRevision >= 0x30) ) {
                    if(VCLKIndex == 0x14) VCLKIndex = 0x2e;
-                }
-              }
+                }
+             }
           }
-        }
+       }
 
      } else {  /* if not programming CRT2 */
 
-        VCLKIndex = VCLKIndexGEN;
-       if(HwInfo->jChipType < SIS_315H) {
-           if(ModeNo > 0x13) {
-             if( (HwInfo->jChipType != SIS_630) &&
-                 (HwInfo->jChipType != SIS_300) ) {
+       VCLKIndex = VCLKIndexGENCRT;
+       if(SiS_Pr->ChipType < SIS_315H) {
+          if(ModeNo > 0x13) {
+             if( (SiS_Pr->ChipType != SIS_630) &&
+                 (SiS_Pr->ChipType != SIS_300) ) {
                 if(VCLKIndex == 0x1b) VCLKIndex = 0x48;
              }
 #if 0
-             if(HwInfo->jChipType == SIS_730) {
+             if(SiS_Pr->ChipType == SIS_730) {
                 if(VCLKIndex == 0x0b) VCLKIndex = 0x40;   /* 1024x768-70 */
                 if(VCLKIndex == 0x0d) VCLKIndex = 0x41;   /* 1024x768-75 */
              }
@@ -2377,11 +2413,13 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "VCLKIndex %d (0x%x)\n", VCLKIndex, VCLKIndex);
+#endif
 #endif
 
-  return(VCLKIndex);
+  return VCLKIndex;
 }
 
 /*********************************************/
@@ -2389,26 +2427,19 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                    PSIS_HW_INFO HwInfo)
+SiS_SetCRT2ModeRegs(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  USHORT i,j,modeflag;
-  USHORT tempcl,tempah=0;
+  unsigned short i, j, modeflag, tempah=0;
+  short tempcl;
 #if defined(SIS300) || defined(SIS315H)
-  USHORT tempbl;
+  unsigned short tempbl;
 #endif
 #ifdef SIS315H
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT tempah2, tempbl2;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short tempah2, tempbl2;
 #endif
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  } else if(SiS_Pr->UseCustomMode) {
-     modeflag = SiS_Pr->CModeFlag;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
+  modeflag = SiS_GetModeFlag(SiS_Pr, ModeNo, ModeIdIndex);
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
 
@@ -2418,18 +2449,18 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   } else {
 
      for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
-     if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->ChipType >= SIS_315H) {
         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
      }
 
      tempcl = SiS_Pr->SiS_ModeType;
 
-     if(HwInfo->jChipType < SIS_315H) {
+     if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300    /* ---- 300 series ---- */
 
-        /* For 301BDH: (with LCD via LVDS) */
-        if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+       /* For 301BDH: (with LCD via LVDS) */
+       if(SiS_Pr->SiS_VBType & VB_NoLCD) {
           tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
           tempbl &= 0xef;
           tempbl |= 0x02;
@@ -2438,16 +2469,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
              tempbl &= 0xfd;
           }
           SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
-        }
+       }
 
-        if(ModeNo > 0x13) {
-           tempcl -= ModeVGA;
-           if((tempcl > 0) || (tempcl == 0)) {      /* tempcl is USHORT -> always true! */
-              tempah = ((0x10 >> tempcl) | 0x80);
-           }
-        } else tempah = 0x80;
+       if(ModeNo > 0x13) {
+          tempcl -= ModeVGA;
+          if(tempcl >= 0) {
+             tempah = ((0x10 >> tempcl) | 0x80);
+          }
+       } else tempah = 0x80;
 
-        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
+       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)  tempah ^= 0xA0;
 
 #endif  /* SIS300 */
 
@@ -2455,22 +2486,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
 #ifdef SIS315H    /* ------- 315/330 series ------ */
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x08);
-           }
-        }
-
-        if(ModeNo > 0x13) {
-           tempcl -= ModeVGA;
-           if((tempcl > 0) || (tempcl == 0)) {  /* tempcl is USHORT -> always true! */
-              tempah = (0x08 >> tempcl);
-              if (tempah == 0) tempah = 1;
-              tempah |= 0x40;
-           }
-        } else tempah = 0x40;
+       if(ModeNo > 0x13) {
+          tempcl -= ModeVGA;
+          if(tempcl >= 0) {
+             tempah = (0x08 >> tempcl);
+             if (tempah == 0) tempah = 1;
+             tempah |= 0x40;
+          }
+       } else tempah = 0x40;
 
-        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
+       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) tempah ^= 0x50;
 
 #endif  /* SIS315H */
 
@@ -2478,84 +2503,89 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
      if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
 
-     if(HwInfo->jChipType < SIS_315H) {
-        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
+     if(SiS_Pr->ChipType < SIS_315H) {
+       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
      } else {
-        if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
-        } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-           if(IS_SIS740) {
+#ifdef SIS315H
+       if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+          if(IS_SIS740) {
              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,tempah);
           } else {
-              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
+             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x00,0xa0,tempah);
           }
-        }
+       }
+#endif
      }
 
      if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-        tempah = 0x01;
-        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-          tempah |= 0x02;
-        }
-        if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-          tempah ^= 0x05;
-          if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-              tempah ^= 0x01;
-          }
-        }
+       tempah = 0x01;
+       if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+          tempah |= 0x02;
+       }
+       if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+          tempah ^= 0x05;
+          if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+             tempah ^= 0x01;
+          }
+       }
 
-        if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
+       if(SiS_Pr->ChipType < SIS_315H) {
 
-        if(HwInfo->jChipType < SIS_315H) {
+          if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
 
-          tempah = (tempah << 5) & 0xFF;
-          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
-          tempah = (tempah >> 5) & 0xFF;
+          tempah = (tempah << 5) & 0xFF;
+          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
+          tempah = (tempah >> 5) & 0xFF;
 
-        } else {
+       } else {
 
-          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF8,tempah);
+          if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0x08;
+          else if(!(SiS_IsDualEdge(SiS_Pr)))           tempah |= 0x08;
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2E,0xF0,tempah);
+          tempah &= ~0x08;
 
-        }
+       }
 
-        if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
-          tempah |= 0x10;
-        }
+       if((SiS_Pr->SiS_ModeType == ModeVGA) && (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+          tempah |= 0x10;
+       }
 
        tempah |= 0x80;
-        if(SiS_Pr->SiS_VBType & VB_SIS301) {
+       if(SiS_Pr->SiS_VBType & VB_SIS301) {
           if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah &= ~0x80;
-        }
+       }
 
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
           if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p | TVSetYPbPr525p))) {
-             if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                 tempah |= 0x20;
+             if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                tempah |= 0x20;
              }
-          }
-        }
+          }
+       }
 
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
+       SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0D,0x40,tempah);
 
        tempah = 0x80;
        if(SiS_Pr->SiS_VBType & VB_SIS301) {
           if(SiS_Pr->PanelXRes < 1280 && SiS_Pr->PanelYRes < 960) tempah = 0;
        }
 
-       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempah |= 0x40;
+       if(SiS_IsDualLink(SiS_Pr)) tempah |= 0x40;
 
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
           if(SiS_Pr->SiS_TVMode & TVRPLLDIV2XO) {
-              tempah |= 0x40;
-                  }
-        }
+             tempah |= 0x40;
+          }
+       }
 
-        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
+       SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0C,tempah);
 
      } else {  /* LVDS */
 
-        if(HwInfo->jChipType >= SIS_315H) {
+       if(SiS_Pr->ChipType >= SIS_315H) {
 
 #ifdef SIS315H
           /* LVDS can only be slave in 8bpp modes */
@@ -2566,36 +2596,30 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
              }
           }
 
-          if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-              tempah |= 0x02;
-          }
+          if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  tempah |= 0x02;
 
-          if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-             tempah ^= 0x01;
-          }
+          if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)        tempah ^= 0x01;
 
-          if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-             tempah = 1;
-          }
+          if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 1;
 
-          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2e,0xF0,tempah);
 #endif
 
-        } else {
+       } else {
 
 #ifdef SIS300
           tempah = 0;
           if( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) && (SiS_Pr->SiS_ModeType > ModeVGA) ) {
-              tempah |= 0x02;
-          }
+             tempah |= 0x02;
+          }
           tempah <<= 5;
 
-          if(SiS_Pr->SiS_VBInfo & DisableCRT2Display)  tempah = 0;
+          if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0;
 
           SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,tempah);
 #endif
 
-        }
+       }
 
      }
 
@@ -2603,10 +2627,10 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->ChipType >= SIS_315H) {
 
 #ifdef SIS315H
-        unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
+       /* unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01); */
 
        /* The following is nearly unpreditable and varies from machine
         * to machine. Especially the 301DH seems to be a real trouble
@@ -2619,25 +2643,28 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
        /* 740 variants match for 30xB, 301B-DH, 30xLV */
 
-        if(!(IS_SIS740)) {
-           tempah = 0x04;                                                 /* For all bridges */
-           tempbl = 0xfb;
-           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-              tempah = 0x00;
-             if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+       if(!(IS_SIS740)) {
+          tempah = 0x04;                                                  /* For all bridges */
+          tempbl = 0xfb;
+          if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+             tempah = 0x00;
+             if(SiS_IsDualEdge(SiS_Pr)) {
                 tempbl = 0xff;
              }
-           }
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
+          }
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
        }
 
        /* The following two are responsible for eventually wrong colors
         * in TV output. The DH (VB_NoLCD) conditions are unknown; the
         * b0 was found in some 651 machine (Pim; P4_23=0xe5); the b1 version
         * in a 650 box (Jake). What is the criteria?
+        * Addendum: Another combination 651+301B-DH(b1) (Rapo) needs same
+        * treatment like the 651+301B-DH(b0) case. Seems more to be the
+        * chipset than the bridge revision.
         */
 
-       if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+       if((IS_SIS740) || (SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
           tempah = 0x30;
           tempbl = 0xc0;
           if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
@@ -2649,20 +2676,30 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0x3f,tempbl);
        } else if(SiS_Pr->SiS_VBType & VB_SIS301) {
           /* Fixes "TV-blue-bug" on 315+301 */
-          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);     /* For 301   */
+          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2c,0xcf);      /* For 301   */
           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
-       } else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);      /* For 30xLV */
-          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
-       } else if((SiS_Pr->SiS_VBType & VB_NoLCD) && (bridgerev == 0xb0)) {
-          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);      /* For 30xB-DH rev b0 (or "DH on 651"?) */
+       } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);       /* For 30xLV */
           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x21,0xc0);
+       } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {              /* For 301B-DH */
+          tempah = 0x30; tempah2 = 0xc0;
+          tempbl = 0xcf; tempbl2 = 0x3f;
+          if(SiS_Pr->SiS_TVBlue == 0) {
+                tempah = tempah2 = 0x00;
+          } else if(SiS_Pr->SiS_TVBlue == -1) {
+             /* Set on 651/M650, clear on 315/650 */
+             if(!(IS_SIS65x)) /* (bridgerev != 0xb0) */ {
+                tempah = tempah2 = 0x00;
+             }
+          }
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2c,tempbl,tempah);
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,tempbl2,tempah2);
        } else {
-          tempah = 0x30; tempah2 = 0xc0;                      /* For 30xB (and 301BDH rev b1) */
+          tempah = 0x30; tempah2 = 0xc0;                      /* For 30xB, 301C */
           tempbl = 0xcf; tempbl2 = 0x3f;
           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
              tempah = tempah2 = 0x00;
-             if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+             if(SiS_IsDualEdge(SiS_Pr)) {
                 tempbl = tempbl2 = 0xff;
              }
           }
@@ -2676,23 +2713,23 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
        } else {
           tempah = 0x00;
-           tempbl = 0x7f;
-           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-              tempbl = 0xff;
-             if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
-           }
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
+          tempbl = 0x7f;
+          if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+             tempbl = 0xff;
+             if(!(SiS_IsDualEdge(SiS_Pr))) tempah = 0x80;
+          }
+          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
        }
 
 #endif /* SIS315H */
 
-     } else if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+     } else if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 
 #ifdef SIS300
-        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
+       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x21,0x3f);
 
-        if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
-           ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+       if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+          ((SiS_Pr->SiS_VBType & VB_NoLCD) &&
            (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x23,0x7F);
        } else {
@@ -2702,9 +2739,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
      }
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
-        if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x0D,0x80);
+       if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
           SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3A,0xC0);
         }
      }
@@ -2712,16 +2749,16 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   } else {  /* LVDS */
 
 #ifdef SIS315H
-     if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->ChipType >= SIS_315H) {
 
-        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+       if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 
-           tempah = 0x04;
+          tempah = 0x04;
           tempbl = 0xfb;
-           if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-              tempah = 0x00;
-             if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
-           }
+          if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+             tempah = 0x00;
+             if(SiS_IsDualEdge(SiS_Pr)) tempbl = 0xff;
+          }
           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
 
           if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
@@ -2730,7 +2767,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
 
-       } else if(HwInfo->jChipType == SIS_550) {
+       } else if(SiS_Pr->ChipType == SIS_550) {
 
           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2c,0x30);
@@ -2748,212 +2785,120 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*            GET RESOLUTION DATA            */
 /*********************************************/
 
-USHORT
-SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex)
+unsigned short
+SiS_GetResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  if(ModeNo <= 0x13) return((USHORT)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
-  else               return((USHORT)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
+   if(ModeNo <= 0x13)
+      return ((unsigned short)SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo);
+   else
+      return ((unsigned short)SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO);
 }
 
 static void
-SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                   PSIS_HW_INFO HwInfo)
+SiS_GetCRT2ResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  USHORT xres,yres,modeflag=0,resindex;
+   unsigned short xres, yres, modeflag=0, resindex;
 
-  if(SiS_Pr->UseCustomMode) {
-     xres = SiS_Pr->CHDisplay;
-     if(SiS_Pr->CModeFlag & HalfDCLK) xres *= 2;
-     SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
-     yres = SiS_Pr->CVDisplay;
-     if(SiS_Pr->CModeFlag & DoubleScanMode) yres *= 2;
-     SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
-     return;
-  }
-
-  resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
+   if(SiS_Pr->UseCustomMode) {
+      xres = SiS_Pr->CHDisplay;
+      if(SiS_Pr->CModeFlag & HalfDCLK) xres <<= 1;
+      SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+      /* DoubleScanMode-check done in CheckCalcCustomMode()! */
+      SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = SiS_Pr->CVDisplay;
+      return;
+   }
 
-  if(ModeNo <= 0x13) {
-     xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
-     yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
-  } else {
-     xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
-     yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-  }
+   resindex = SiS_GetResInfo(SiS_Pr,ModeNo,ModeIdIndex);
 
-  if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
+   if(ModeNo <= 0x13) {
+      xres = SiS_Pr->SiS_StResInfo[resindex].HTotal;
+      yres = SiS_Pr->SiS_StResInfo[resindex].VTotal;
+   } else {
+      xres = SiS_Pr->SiS_ModeResInfo[resindex].HTotal;
+      yres = SiS_Pr->SiS_ModeResInfo[resindex].VTotal;
+      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+   }
 
-     if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
-        if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-           if(yres == 350) yres = 400;
-        }
-        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
-          if(ModeNo == 0x12) yres = 400;
-        }
-     }
+   if(!SiS_Pr->SiS_IF_DEF_DSTN && !SiS_Pr->SiS_IF_DEF_FSTN) {
 
-     if(modeflag & HalfDCLK)       xres *= 2;
-     if(modeflag & DoubleScanMode) yres *= 2;
+      if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_IF_DEF_LVDS == 1)) {
+        if((ModeNo != 0x03) && (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+           if(yres == 350) yres = 400;
+        }
+        if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x3a) & 0x01) {
+           if(ModeNo == 0x12) yres = 400;
+        }
+      }
 
-  }
+      if(modeflag & HalfDCLK)       xres <<= 1;
+      if(modeflag & DoubleScanMode) yres <<= 1;
 
-  if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+   }
 
-#if 0
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
-           if(xres == 720) xres = 640;
-       }
-#endif
+   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
 
-       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-          switch(SiS_Pr->SiS_LCDResInfo) {
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+        switch(SiS_Pr->SiS_LCDResInfo) {
           case Panel_1024x768:
              if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-                 if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-                   if(yres == 350) yres = 357;
-                   if(yres == 400) yres = 420;
-                   if(yres == 480) yres = 525;
-                }
-             }
+                if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
+                   if(yres == 350) yres = 357;
+                   if(yres == 400) yres = 420;
+                   if(yres == 480) yres = 525;
+                }
+             }
              break;
           case Panel_1280x1024:
              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
                 /* BIOS bug - does this regardless of scaling */
-                if(yres == 400) yres = 405;
+                if(yres == 400) yres = 405;
+             }
+             if(yres == 350) yres = 360;
+             if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+                if(yres == 360) yres = 375;
              }
-             if(yres == 350) yres = 360;
-             if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-                 if(yres == 360) yres = 375;
-             }
              break;
           case Panel_1600x1200:
              if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-                if(yres == 1024) yres = 1056;
-             }
+                if(yres == 1024) yres = 1056;
+             }
              break;
-          }
-       }
+        }
+      }
 
-  } else {
+   } else {
 
-     if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
-           if(xres == 720) xres = 640;
-       }
-     } else if(xres == 720) xres = 640;
+      if(SiS_Pr->SiS_VBType & VB_SISVB) {
+        if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToHiVision)) {
+           if(xres == 720) xres = 640;
+        }
+      } else if(xres == 720) xres = 640;
 
-     if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-       yres = 400;
-        if(HwInfo->jChipType >= SIS_315H) {
-           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
-        } else {
-           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
-        }
-        if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN)  yres = 480;
-     }
+      if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
+        yres = 400;
+        if(SiS_Pr->ChipType >= SIS_315H) {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x17) & 0x80) yres = 480;
+        } else {
+           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) yres = 480;
+        }
+        if(SiS_Pr->SiS_IF_DEF_DSTN || SiS_Pr->SiS_IF_DEF_FSTN) yres = 480;
+      }
 
-  }
-  SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
-  SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
+   }
+   SiS_Pr->SiS_VGAHDE = SiS_Pr->SiS_HDE = xres;
+   SiS_Pr->SiS_VGAVDE = SiS_Pr->SiS_VDE = yres;
 }
 
 /*********************************************/
 /*           GET CRT2 TIMING DATA            */
 /*********************************************/
 
-static BOOLEAN
-SiS_GetLVDSCRT1Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                  USHORT RefreshRateTableIndex, USHORT *ResIndex,
-                  USHORT *DisplayType)
- {
-  USHORT modeflag=0;
-
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
-        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return FALSE;
-     }
-  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
-     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))    return FALSE;
-  } else
-     return FALSE;
-
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
-
-  (*ResIndex) &= 0x3F;
-
-  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-     (*DisplayType) = 18;
-     if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
-     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-       (*DisplayType) += 2;
-       if(SiS_Pr->SiS_ModeType > ModeVGA) {
-          if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 99;
-       }
-       if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-          (*DisplayType) = 18;  /* PALM uses NTSC data */
-          if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
-       } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-          (*DisplayType) = 20;  /* PALN uses PAL data  */
-          if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
-       }
-     }
-  } else {
-     switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_640x480:   (*DisplayType) = 50; break;
-     case Panel_640x480_2: (*DisplayType) = 52; break;
-     case Panel_640x480_3: (*DisplayType) = 54; break;
-     case Panel_800x600:   (*DisplayType) =  0; break;
-     case Panel_1024x600:  (*DisplayType) = 23; break;
-     case Panel_1024x768:  (*DisplayType) =  4; break;
-     case Panel_1152x768:  (*DisplayType) = 27; break;
-     case Panel_1280x768:  (*DisplayType) = 40; break;
-     case Panel_1280x1024: (*DisplayType) =  8; break;
-     case Panel_1400x1050: (*DisplayType) = 14; break;
-     case Panel_1600x1200: (*DisplayType) = 36; break;
-     default: return FALSE;
-     }
-
-     if(modeflag & HalfDCLK) (*DisplayType)++;
-
-     switch(SiS_Pr->SiS_LCDResInfo) {
-     case Panel_640x480:
-     case Panel_640x480_2:
-     case Panel_640x480_3:
-        break;
-     default:
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
-     }
-
-     if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-        (*DisplayType) = 12;
-       if(modeflag & HalfDCLK) (*DisplayType)++;
-     }
-  }
-
-#if 0
-  if(SiS_Pr->SiS_IF_DEF_FSTN) {
-     if(SiS_Pr->SiS_LCDResInfo == SiS_Pr->SiS_Panel320x480){
-        (*DisplayType) = 22;
-     }
-  }
-#endif
-
-  return TRUE;
-}
-
 static void
-SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-              USHORT RefreshRateTableIndex,USHORT *CRT2Index,USHORT *ResIndex,
-              PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+              unsigned short RefreshRateTableIndex, unsigned short *CRT2Index,
+              unsigned short *ResIndex)
 {
-  USHORT tempbx=0,tempal=0,resinfo=0;
+  unsigned short tempbx=0, tempal=0, resinfo=0;
 
   if(ModeNo <= 0x13) {
      tempal = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -2966,18 +2911,20 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {                            /* LCD */
 
-        tempbx = SiS_Pr->SiS_LCDResInfo;
+       tempbx = SiS_Pr->SiS_LCDResInfo;
        if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
 
+       /* patch index */
        if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
           if     (resinfo == SIS_RI_1280x800)  tempal =  9;
           else if(resinfo == SIS_RI_1400x1050) tempal = 11;
        } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x800) ||
-                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2)) {
+                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x800_2) ||
+                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x854)) {
           if     (resinfo == SIS_RI_1280x768)  tempal =  9;
        }
 
-       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
           /* Pass 1:1 only (center-screen handled outside) */
           /* This is never called for the panel's native resolution */
           /* since Pass1:1 will not be set in this case */
@@ -2991,8 +2938,8 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
           if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
              if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-                tempbx = 200;
-                if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
+                tempbx = 200;
+                if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx++;
              }
           }
        }
@@ -3000,23 +2947,23 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 
      } else {                                                  /* TV */
 
-       if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-           /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
-           tempbx = 2;
-           if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+       if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+          /* if(SiS_Pr->SiS_VGAVDE > 480) SiS_Pr->SiS_TVMode &= (~TVSetTVSimuMode); */
+          tempbx = 2;
+          if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
              tempbx = 13;
-              if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
-           }
+             if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) tempbx = 14;
+          }
        } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-          if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
-          else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
-          else                                         tempbx = 5;
-          if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
-               } else {
-           if(SiS_Pr->SiS_TVMode & TVSetPAL)           tempbx = 3;
-           else                                        tempbx = 4;
-           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)    tempbx += 5;
-               }
+          if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      tempbx = 7;
+          else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) tempbx = 6;
+          else                                         tempbx = 5;
+          if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
+       } else {
+          if(SiS_Pr->SiS_TVMode & TVSetPAL)            tempbx = 3;
+          else                                         tempbx = 4;
+          if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)     tempbx += 5;
+       }
 
      }
 
@@ -3024,26 +2971,34 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 
      if(ModeNo > 0x13) {
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) {
-          if(tempal == 6) tempal = 7;
-           if((resinfo == SIS_RI_720x480) ||
-             (resinfo == SIS_RI_720x576) ||
-             (resinfo == SIS_RI_768x576)) {
+          switch(resinfo) {
+          case SIS_RI_720x480:
              tempal = 6;
-             if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
-                if(resinfo == SIS_RI_720x480) tempal = 9;
+             if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN))   tempal = 9;
+             break;
+          case SIS_RI_720x576:
+          case SIS_RI_768x576:
+          case SIS_RI_1024x576: /* Not in NTSC or YPBPR mode (except 1080i)! */
+             tempal = 6;
+             if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+                if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)        tempal = 8;
              }
-          }
-          if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-              if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-                if(resinfo == SIS_RI_1024x768) tempal = 8;
+             break;
+          case SIS_RI_800x480:
+             tempal = 4;
+             break;
+          case SIS_RI_512x384:
+          case SIS_RI_1024x768:
+             tempal = 7;
+             if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+                if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p)        tempal = 8;
              }
-             if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-                if((resinfo == SIS_RI_720x576) ||
-                   (resinfo == SIS_RI_768x576)) {
-                   tempal = 8;
-                }
-                if(resinfo == SIS_RI_1280x720) tempal = 9;
+             break;
+          case SIS_RI_1280x720:
+             if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
+                if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)        tempal = 9;
              }
+             break;
           }
        }
      }
@@ -3056,65 +3011,60 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
      tempbx = 0;
      if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
 
-        tempbx = 10;
-       if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-          tempbx += 2;
+       tempbx = 90;
+       if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+          tempbx = 92;
           if(SiS_Pr->SiS_ModeType > ModeVGA) {
              if(SiS_Pr->SiS_CHSOverScan) tempbx = 99;
           }
-          if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-             tempbx = 90;
-             if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-          } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-             tempbx = 92;
-             if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx += 1;
-          }
-        }
+          if(SiS_Pr->SiS_TVMode & TVSetPALM)      tempbx = 94;
+          else if(SiS_Pr->SiS_TVMode & TVSetPALN) tempbx = 96;
+       }
+       if(tempbx != 99) {
+          if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) tempbx++;
+       }
 
      } else {
 
-        switch(SiS_Pr->SiS_LCDResInfo) {
-       case Panel_640x480:   tempbx = 6;  break;
-       case Panel_640x480_2:
-       case Panel_640x480_3: tempbx = 30; break;
-       case Panel_800x600:   tempbx = 0;  break;
-       case Panel_1024x600:  tempbx = 15; break;
-       case Panel_1024x768:  tempbx = 2;  break;
-       case Panel_1152x768:  tempbx = 17; break;
-       case Panel_1280x768:  tempbx = 18; break;
-       case Panel_1280x1024: tempbx = 4;  break;
-       case Panel_1400x1050: tempbx = 8;  break;
-       case Panel_1600x1200: tempbx = 21; break;
+       switch(SiS_Pr->SiS_LCDResInfo) {
+       case Panel_640x480:   tempbx = 12; break;
+       case Panel_320x240_1: tempbx = 10; break;
+       case Panel_320x240_2:
+       case Panel_320x240_3: tempbx = 14; break;
+       case Panel_800x600:   tempbx = 16; break;
+       case Panel_1024x600:  tempbx = 18; break;
+       case Panel_1152x768:
+       case Panel_1024x768:  tempbx = 20; break;
+       case Panel_1280x768:  tempbx = 22; break;
+       case Panel_1280x1024: tempbx = 24; break;
+       case Panel_1400x1050: tempbx = 26; break;
+       case Panel_1600x1200: tempbx = 28; break;
+#ifdef SIS300
        case Panel_Barco1366: tempbx = 80; break;
+#endif
        }
 
        switch(SiS_Pr->SiS_LCDResInfo) {
+       case Panel_320x240_1:
+       case Panel_320x240_2:
+       case Panel_320x240_3:
        case Panel_640x480:
-       case Panel_640x480_2:
-       case Panel_640x480_3:
           break;
        default:
           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
        }
 
-       if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 7;
+       if(SiS_Pr->SiS_LCDInfo & LCDPass11) tempbx = 30;
 
+#ifdef SIS300
        if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
           tempbx = 82;
           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
-       } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848) {
+       } else if(SiS_Pr->SiS_CustomT == CUT_PANEL848 || SiS_Pr->SiS_CustomT == CUT_PANEL856) {
           tempbx = 84;
           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) tempbx++;
        }
-
-       if((SiS_Pr->SiS_CustomT != CUT_BARCO1366) &&
-           (SiS_Pr->SiS_CustomT != CUT_PANEL848)) {
-           if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
-             (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-              tempal = 0;
-          }
-        }
+#endif
 
      }
 
@@ -3124,12 +3074,11 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 }
 
 static void
-SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex,PSIS_HW_INFO HwInfo)
+SiS_GetRAMDAC2DATA(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
 {
-  USHORT tempax=0,tempbx=0;
-  USHORT temp1=0,modeflag=0,tempcx=0;
-  USHORT index;
+  unsigned short tempax=0, tempbx=0, index, dotclock;
+  unsigned short temp1=0, modeflag=0, tempcx=0;
 
   SiS_Pr->SiS_RVBHCMAX  = 1;
   SiS_Pr->SiS_RVBHCFACT = 1;
@@ -3143,10 +3092,12 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
      tempbx = SiS_Pr->SiS_StandTable[index].CRTC[6];
      temp1 = SiS_Pr->SiS_StandTable[index].CRTC[7];
 
+     dotclock = (modeflag & Charx8Dot) ? 8 : 9;
+
   } else {
 
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+     index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
 
      tempax = SiS_Pr->SiS_CRT1Table[index].CR[0];
      tempax |= (SiS_Pr->SiS_CRT1Table[index].CR[14] << 8);
@@ -3158,22 +3109,16 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
      tempbx |= tempcx;
      temp1  = SiS_Pr->SiS_CRT1Table[index].CR[7];
 
+     dotclock = 8;
+
   }
 
   if(temp1 & 0x01) tempbx |= 0x0100;
   if(temp1 & 0x20) tempbx |= 0x0200;
 
   tempax += 5;
-
-  /* Charx8Dot is no more used (and assumed), so we set it */
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-     modeflag |= Charx8Dot;
-  }
-
-  if(modeflag & Charx8Dot) tempax *= 8;
-  else                     tempax *= 9;
-
-  if(modeflag & HalfDCLK)  tempax <<= 1;
+  tempax *= dotclock;
+  if(modeflag & HalfDCLK) tempax <<= 1;
 
   tempbx++;
 
@@ -3182,13 +3127,56 @@ SiS_GetRAMDAC2DATA(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 }
 
 static void
-SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                    USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_CalcPanelLinkTiming(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex)
+{
+   unsigned short ResIndex;
+
+   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+      if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+        if(SiS_Pr->UseCustomMode) {
+           ResIndex = SiS_Pr->CHTotal;
+           if(SiS_Pr->CModeFlag & HalfDCLK) ResIndex <<= 1;
+           SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = ResIndex;
+           SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
+        } else {
+           if(ModeNo < 0x13) {
+              ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+           } else {
+              ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
+           }
+           if(ResIndex == 0x09) {
+              if(SiS_Pr->Alternate1600x1200)        ResIndex = 0x20; /* 1600x1200 LCDA */
+              else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) ResIndex = 0x21; /* 1600x1200 LVDS */
+           }
+           SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
+           SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
+           SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
+           SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
+        }
+      } else {
+        SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
+        SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
+      }
+   } else {
+      /* This handles custom modes and custom panels */
+      SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+      SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+      SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
+      SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
+      SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
+      SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
+   }
+}
+
+static void
+SiS_GetCRT2DataLVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                    unsigned short RefreshRateTableIndex)
 {
-   USHORT CRT2Index, ResIndex;
-   const SiS_LVDSDataStruct *LVDSData = NULL;
+   unsigned short CRT2Index, ResIndex, backup;
+   const struct SiS_LVDSData *LVDSData = NULL;
 
-   SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+   SiS_GetCRT2ResInfo(SiS_Pr, ModeNo, ModeIdIndex);
 
    if(SiS_Pr->SiS_VBType & VB_SISVB) {
       SiS_Pr->SiS_RVBHCMAX  = 1;
@@ -3199,133 +3187,94 @@ SiS_GetCRT2DataLVDS(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
       SiS_Pr->SiS_RY2COE = 0;
       SiS_Pr->SiS_RY3COE = 0;
       SiS_Pr->SiS_RY4COE = 0;
+      SiS_Pr->SiS_RVBHRS2 = 0;
    }
 
    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
-      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-         if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-           if(SiS_Pr->UseCustomMode) {
-              SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->CHTotal;
-              SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
-           } else {
-              if(ModeNo < 0x13) {
-                 ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-              } else {
-                 ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC_NS;
-              }
-              SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAHT;
-               SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_NoScaleData[ResIndex].VGAVT;
-               SiS_Pr->SiS_HT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDHT;
-               SiS_Pr->SiS_VT    = SiS_Pr->SiS_NoScaleData[ResIndex].LCDVT;
-           }
-        } else {
-           SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = SiS_Pr->PanelHT;
-            SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->PanelVT;
-        }
-      } else {
-        /* This handles custom modes and custom panels */
-        SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-         SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-         SiS_Pr->SiS_HT  = SiS_Pr->PanelHT;
-         SiS_Pr->SiS_VT  = SiS_Pr->PanelVT;
-        SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT - (SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE);
-        SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT - (SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE);
-      }
-
-      SiS_CalcLCDACRT1Timing(SiS_Pr,ModeNo,ModeIdIndex);
-
+      SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
 #endif
 
    } else {
 
       /* 301BDH needs LVDS Data */
+      backup = SiS_Pr->SiS_IF_DEF_LVDS;
       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
         SiS_Pr->SiS_IF_DEF_LVDS = 1;
       }
 
       SiS_GetCRT2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                               &CRT2Index, &ResIndex, HwInfo);
+                                           &CRT2Index, &ResIndex);
 
-      /* 301BDH needs LVDS Data */
-      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-         SiS_Pr->SiS_IF_DEF_LVDS = 0;
-      }
+      SiS_Pr->SiS_IF_DEF_LVDS = backup;
 
-      switch (CRT2Index) {
-        case  0: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
-        case  1: LVDSData = SiS_Pr->SiS_LVDS800x600Data_2;    break;
-        case  2: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
-        case  3: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_2;   break;
-        case  4: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_1;  break;
-        case  5: LVDSData = SiS_Pr->SiS_LVDS1280x1024Data_2;  break;
-        case  6: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
-         case  7: LVDSData = SiS_Pr->SiS_LVDSXXXxXXXData_1;    break;
-        case  8: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_1;  break;
-        case  9: LVDSData = SiS_Pr->SiS_LVDS1400x1050Data_2;  break;
-        case 10: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
-        case 11: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
-        case 12: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
-        case 13: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
-        case 14: LVDSData = SiS_Pr->SiS_LVDS320x480Data_1;    break;
-        case 15: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
-        case 16: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_2;   break;
-        case 17: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_1;   break;
-        case 18: LVDSData = SiS_Pr->SiS_LVDS1152x768Data_2;   break;
-        case 19: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_1;   break;
-        case 20: LVDSData = SiS_Pr->SiS_LVDS1280x768Data_2;   break;
-        case 21: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_1;  break;
-        case 22: LVDSData = SiS_Pr->SiS_LVDS1600x1200Data_2;  break;
-        case 30: LVDSData = SiS_Pr->SiS_LVDS640x480Data_2;    break;
+      switch(CRT2Index) {
+        case 10: LVDSData = SiS_Pr->SiS_LVDS320x240Data_1;    break;
+        case 14: LVDSData = SiS_Pr->SiS_LVDS320x240Data_2;    break;
+        case 12: LVDSData = SiS_Pr->SiS_LVDS640x480Data_1;    break;
+        case 16: LVDSData = SiS_Pr->SiS_LVDS800x600Data_1;    break;
+        case 18: LVDSData = SiS_Pr->SiS_LVDS1024x600Data_1;   break;
+        case 20: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+#ifdef SIS300
         case 80: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_1;  break;
         case 81: LVDSData = SiS_Pr->SiS_LVDSBARCO1366Data_2;  break;
         case 82: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_1;  break;
-        case 83: LVDSData = SiS_Pr->SiS_LVDSBARCO1024Data_2;  break;
         case 84: LVDSData = SiS_Pr->SiS_LVDS848x480Data_1;    break;
         case 85: LVDSData = SiS_Pr->SiS_LVDS848x480Data_2;    break;
-        case 90: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
-        case 91: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
-        case 92: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
-        case 93: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
-        case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;        break;  /* Super Overscan */
-        default: LVDSData = SiS_Pr->SiS_LVDS1024x768Data_1;   break;
+#endif
+        case 90: LVDSData = SiS_Pr->SiS_CHTVUNTSCData;        break;
+        case 91: LVDSData = SiS_Pr->SiS_CHTVONTSCData;        break;
+        case 92: LVDSData = SiS_Pr->SiS_CHTVUPALData;         break;
+        case 93: LVDSData = SiS_Pr->SiS_CHTVOPALData;         break;
+        case 94: LVDSData = SiS_Pr->SiS_CHTVUPALMData;        break;
+        case 95: LVDSData = SiS_Pr->SiS_CHTVOPALMData;        break;
+        case 96: LVDSData = SiS_Pr->SiS_CHTVUPALNData;        break;
+        case 97: LVDSData = SiS_Pr->SiS_CHTVOPALNData;        break;
+        case 99: LVDSData = SiS_Pr->SiS_CHTVSOPALData;        break;
       }
 
-      SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
-      SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
-      SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
-      SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
-
-      if(!(SiS_Pr->SiS_VBType & VB_SISVB)) {
-         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
-            if((!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) || (SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-              SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
-               SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
-              if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
-                 if(ResIndex < 0x08) {
-                    SiS_Pr->SiS_HDE = 1280;
-                     SiS_Pr->SiS_VDE = 1024;
-                  }
-               }
-            }
+      if(LVDSData) {
+        SiS_Pr->SiS_VGAHT = (LVDSData+ResIndex)->VGAHT;
+        SiS_Pr->SiS_VGAVT = (LVDSData+ResIndex)->VGAVT;
+        SiS_Pr->SiS_HT    = (LVDSData+ResIndex)->LCDHT;
+        SiS_Pr->SiS_VT    = (LVDSData+ResIndex)->LCDVT;
+      } else {
+        SiS_CalcPanelLinkTiming(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      }
+
+      if( (!(SiS_Pr->SiS_VBType & VB_SISVB)) &&
+         (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) &&
+         (!(SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+        if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ||
+            (SiS_Pr->SiS_SetFlag & SetDOSMode) ) {
+           SiS_Pr->SiS_HDE = SiS_Pr->PanelXRes;
+            SiS_Pr->SiS_VDE = SiS_Pr->PanelYRes;
+#ifdef SIS300
+           if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+              if(ResIndex < 0x08) {
+                 SiS_Pr->SiS_HDE = 1280;
+                 SiS_Pr->SiS_VDE = 1024;
+              }
+           }
+#endif
          }
       }
    }
 }
 
 static void
-SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex,
-                  PSIS_HW_INFO HwInfo)
-{
-  UCHAR  *ROMAddr = NULL;
-  USHORT tempax,tempbx,modeflag,romptr=0;
-  USHORT resinfo,CRT2Index,ResIndex;
-  const SiS_LCDDataStruct *LCDPtr = NULL;
-  const SiS_TVDataStruct  *TVPtr  = NULL;
+SiS_GetCRT2Data301(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
+{
+  unsigned char  *ROMAddr = NULL;
+  unsigned short tempax, tempbx, modeflag, romptr=0;
+  unsigned short resinfo, CRT2Index, ResIndex;
+  const struct SiS_LCDData *LCDPtr = NULL;
+  const struct SiS_TVData  *TVPtr  = NULL;
 #ifdef SIS315H
-  SHORT  resinfo661;
+  short resinfo661;
 #endif
 
   if(ModeNo <= 0x13) {
@@ -3340,67 +3289,69 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 #ifdef SIS315H
      resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
-         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
-         (resinfo661 >= 0)                     &&
+        (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+        (resinfo661 >= 0)                     &&
         (SiS_Pr->SiS_NeedRomModeData) ) {
-        if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+       if((ROMAddr = GetLCDStructPtr661(SiS_Pr))) {
           if((romptr = (SISGETROMW(21)))) {
-              romptr += (resinfo661 * 10);
-             ROMAddr = HwInfo->pjVirtualRomBase;
+             romptr += (resinfo661 * 10);
+             ROMAddr = SiS_Pr->VirtualRomBase;
           }
        }
      }
 #endif
   }
-  
+
   SiS_Pr->SiS_NewFlickerMode = 0;
   SiS_Pr->SiS_RVBHRS = 50;
   SiS_Pr->SiS_RY1COE = 0;
   SiS_Pr->SiS_RY2COE = 0;
   SiS_Pr->SiS_RY3COE = 0;
   SiS_Pr->SiS_RY4COE = 0;
+  SiS_Pr->SiS_RVBHRS2 = 0;
 
-  SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex,HwInfo);
+  SiS_GetCRT2ResInfo(SiS_Pr,ModeNo,ModeIdIndex);
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC){
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
 
      if(SiS_Pr->UseCustomMode) {
 
-        SiS_Pr->SiS_RVBHCMAX  = 1;
-        SiS_Pr->SiS_RVBHCFACT = 1;
-        SiS_Pr->SiS_VGAHT     = SiS_Pr->CHTotal;
-        SiS_Pr->SiS_VGAVT     = SiS_Pr->CVTotal;
-        SiS_Pr->SiS_HT        = SiS_Pr->CHTotal;
-        SiS_Pr->SiS_VT        = SiS_Pr->CVTotal;
+       SiS_Pr->SiS_RVBHCMAX  = 1;
+       SiS_Pr->SiS_RVBHCFACT = 1;
        SiS_Pr->SiS_HDE       = SiS_Pr->SiS_VGAHDE;
-        SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
+       SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
+
+       tempax = SiS_Pr->CHTotal;
+       if(modeflag & HalfDCLK) tempax <<= 1;
+       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+       SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
 
      } else {
 
-        SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+       SiS_GetRAMDAC2DATA(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 
      SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                    &CRT2Index,&ResIndex,HwInfo);
+                   &CRT2Index,&ResIndex);
 
      switch(CRT2Index) {
-        case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
-        case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
-        case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
-        case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
-        case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
-        case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
-        case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
-        case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
-        case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
-        case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
-        case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
-        case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
-        case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
-        default: TVPtr = SiS_Pr->SiS_StPALData;     break;
+       case  2: TVPtr = SiS_Pr->SiS_ExtHiTVData;   break;
+       case  3: TVPtr = SiS_Pr->SiS_ExtPALData;    break;
+       case  4: TVPtr = SiS_Pr->SiS_ExtNTSCData;   break;
+       case  5: TVPtr = SiS_Pr->SiS_Ext525iData;   break;
+       case  6: TVPtr = SiS_Pr->SiS_Ext525pData;   break;
+       case  7: TVPtr = SiS_Pr->SiS_Ext750pData;   break;
+       case  8: TVPtr = SiS_Pr->SiS_StPALData;     break;
+       case  9: TVPtr = SiS_Pr->SiS_StNTSCData;    break;
+       case 10: TVPtr = SiS_Pr->SiS_St525iData;    break;
+       case 11: TVPtr = SiS_Pr->SiS_St525pData;    break;
+       case 12: TVPtr = SiS_Pr->SiS_St750pData;    break;
+       case 13: TVPtr = SiS_Pr->SiS_St1HiTVData;   break;
+       case 14: TVPtr = SiS_Pr->SiS_St2HiTVData;   break;
+       default: TVPtr = SiS_Pr->SiS_StPALData;     break;
      }
 
      SiS_Pr->SiS_RVBHCMAX  = (TVPtr+ResIndex)->RVBHCMAX;
@@ -3409,73 +3360,77 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
      SiS_Pr->SiS_VGAVT     = (TVPtr+ResIndex)->VGAVT;
      SiS_Pr->SiS_HDE       = (TVPtr+ResIndex)->TVHDE;
      SiS_Pr->SiS_VDE       = (TVPtr+ResIndex)->TVVDE;
-     SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
-     SiS_Pr->SiS_NewFlickerMode = (TVPtr+ResIndex)->FlickerMode;
+     SiS_Pr->SiS_RVBHRS2   = (TVPtr+ResIndex)->RVBHRS2 & 0x0fff;
      if(modeflag & HalfDCLK) {
-        SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+       SiS_Pr->SiS_RVBHRS = (TVPtr+ResIndex)->HALFRVBHRS;
+       if(SiS_Pr->SiS_RVBHRS2) {
+          SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+          tempax = ((TVPtr+ResIndex)->RVBHRS2 >> 12) & 0x07;
+          if((TVPtr+ResIndex)->RVBHRS2 & 0x8000) SiS_Pr->SiS_RVBHRS2 -= tempax;
+          else                                   SiS_Pr->SiS_RVBHRS2 += tempax;
+       }
+     } else {
+       SiS_Pr->SiS_RVBHRS    = (TVPtr+ResIndex)->RVBHRS;
      }
+     SiS_Pr->SiS_NewFlickerMode = ((TVPtr+ResIndex)->FlickerMode) << 7;
 
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
-        if((resinfo == SIS_RI_1024x768)  ||
-           (resinfo == SIS_RI_1280x1024) ||
-           (resinfo == SIS_RI_1280x720)) {
+       if((resinfo == SIS_RI_960x600)   ||
+          (resinfo == SIS_RI_1024x768)  ||
+          (resinfo == SIS_RI_1280x1024) ||
+          (resinfo == SIS_RI_1280x720)) {
           SiS_Pr->SiS_NewFlickerMode = 0x40;
        }
 
-        if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
+       if(SiS_Pr->SiS_VGAVDE == 350) SiS_Pr->SiS_TVMode |= TVSetTVSimuMode;
 
-        SiS_Pr->SiS_HT = ExtHiTVHT;
-        SiS_Pr->SiS_VT = ExtHiTVVT;
-        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-           if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-              SiS_Pr->SiS_HT = StHiTVHT;
-              SiS_Pr->SiS_VT = StHiTVVT;
-#if 0
-              if(!(modeflag & Charx8Dot)) {
-                 SiS_Pr->SiS_HT = StHiTextTVHT;
-                 SiS_Pr->SiS_VT = StHiTextTVVT;
-              }
-#endif
-           }
-        }
+       SiS_Pr->SiS_HT = ExtHiTVHT;
+       SiS_Pr->SiS_VT = ExtHiTVVT;
+       if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+          if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+             SiS_Pr->SiS_HT = StHiTVHT;
+             SiS_Pr->SiS_VT = StHiTVVT;
+          }
+       }
 
      } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 
-        if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-           SiS_Pr->SiS_HT = 1650;
-           SiS_Pr->SiS_VT = 750;
+       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
+          SiS_Pr->SiS_HT = 1650;
+          SiS_Pr->SiS_VT = 750;
        } else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
           SiS_Pr->SiS_HT = NTSCHT;
+          if(SiS_Pr->SiS_TVMode & TVSet525p1024) SiS_Pr->SiS_HT = NTSC2HT;
           SiS_Pr->SiS_VT = NTSCVT;
-        } else {
-           SiS_Pr->SiS_HT = NTSCHT;
+       } else {
+          SiS_Pr->SiS_HT = NTSCHT;
           if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
-           SiS_Pr->SiS_VT = NTSCVT;
-        }
+          SiS_Pr->SiS_VT = NTSCVT;
+       }
 
      } else {
 
-        SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
-        SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
-        SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
-        SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
+       SiS_Pr->SiS_RY1COE = (TVPtr+ResIndex)->RY1COE;
+       SiS_Pr->SiS_RY2COE = (TVPtr+ResIndex)->RY2COE;
+       SiS_Pr->SiS_RY3COE = (TVPtr+ResIndex)->RY3COE;
+       SiS_Pr->SiS_RY4COE = (TVPtr+ResIndex)->RY4COE;
 
-        if(modeflag & HalfDCLK) {
-           SiS_Pr->SiS_RY1COE = 0x00;
-           SiS_Pr->SiS_RY2COE = 0xf4;
-           SiS_Pr->SiS_RY3COE = 0x10;
-           SiS_Pr->SiS_RY4COE = 0x38;
-        }
+       if(modeflag & HalfDCLK) {
+          SiS_Pr->SiS_RY1COE = 0x00;
+          SiS_Pr->SiS_RY2COE = 0xf4;
+          SiS_Pr->SiS_RY3COE = 0x10;
+          SiS_Pr->SiS_RY4COE = 0x38;
+       }
 
-        if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-           SiS_Pr->SiS_HT = NTSCHT;
+       if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+          SiS_Pr->SiS_HT = NTSCHT;
           if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) SiS_Pr->SiS_HT = NTSC2HT;
-           SiS_Pr->SiS_VT = NTSCVT;
-        } else {
-           SiS_Pr->SiS_HT = PALHT;
-           SiS_Pr->SiS_VT = PALVT;
-        }
+          SiS_Pr->SiS_VT = NTSCVT;
+       } else {
+          SiS_Pr->SiS_HT = PALHT;
+          SiS_Pr->SiS_VT = PALVT;
+       }
 
      }
 
@@ -3486,42 +3441,53 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 
      if(SiS_Pr->UseCustomMode) {
 
-        SiS_Pr->SiS_VGAHT = SiS_Pr->CHTotal;
-        SiS_Pr->SiS_VGAVT = SiS_Pr->CVTotal;
-        SiS_Pr->SiS_HT    = SiS_Pr->CHTotal;
-        SiS_Pr->SiS_VT    = SiS_Pr->CVTotal;
        SiS_Pr->SiS_HDE   = SiS_Pr->SiS_VGAHDE;
-        SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
+       SiS_Pr->SiS_VDE   = SiS_Pr->SiS_VGAVDE;
+
+       tempax = SiS_Pr->CHTotal;
+       if(modeflag & HalfDCLK) tempax <<= 1;
+       SiS_Pr->SiS_VGAHT = SiS_Pr->SiS_HT = tempax;
+       SiS_Pr->SiS_VGAVT = SiS_Pr->SiS_VT = SiS_Pr->CVTotal;
 
      } else {
 
-        BOOLEAN gotit = FALSE;
+       BOOLEAN gotit = FALSE;
 
-        if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
+       if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
 
-           SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
-           SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
-           SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
-           SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
+          SiS_Pr->SiS_VGAHT = SiS_Pr->PanelHT;
+          SiS_Pr->SiS_VGAVT = SiS_Pr->PanelVT;
+          SiS_Pr->SiS_HT    = SiS_Pr->PanelHT;
+          SiS_Pr->SiS_VT    = SiS_Pr->PanelVT;
           gotit = TRUE;
 
        } else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
 
 #ifdef SIS315H
           SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
-           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
-           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
-           SiS_Pr->SiS_VGAVT     = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
-           SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
-           SiS_Pr->SiS_VT        = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
+          SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+          SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+          SiS_Pr->SiS_VGAVT     = (ROMAddr[romptr+4] << 4) | ((ROMAddr[romptr+3] & 0xf0) >> 4);
+          SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+          SiS_Pr->SiS_VT        = (ROMAddr[romptr+7] << 4) | ((ROMAddr[romptr+6] & 0xf0) >> 4);
+          SiS_Pr->SiS_RVBHRS2   = ROMAddr[romptr+8] | ((ROMAddr[romptr+9] & 0x0f) << 8);
+          if((SiS_Pr->SiS_RVBHRS2) && (modeflag & HalfDCLK)) {
+             SiS_Pr->SiS_RVBHRS2 = ((SiS_Pr->SiS_RVBHRS2 + 3) >> 1) - 3;
+             tempax = (ROMAddr[romptr+9] >> 4) & 0x07;
+             if(ROMAddr[romptr+9] & 0x80) SiS_Pr->SiS_RVBHRS2 -= tempax;
+             else                         SiS_Pr->SiS_RVBHRS2 += tempax;
+          }
           if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
           else {
              SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
              SiS_Pr->SiS_LCDInfo &= ~LCDPass11;
+             SiS_Pr->SiS_RVBHCMAX  = 1;
+             SiS_Pr->SiS_RVBHCFACT = 1;
              SiS_Pr->SiS_VGAHT   = SiS_Pr->PanelHT;
-              SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
-              SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
-              SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
+             SiS_Pr->SiS_VGAVT   = SiS_Pr->PanelVT;
+             SiS_Pr->SiS_HT      = SiS_Pr->PanelHT;
+             SiS_Pr->SiS_VT      = SiS_Pr->PanelVT;
+             SiS_Pr->SiS_RVBHRS2 = 0;
              gotit = TRUE;
           }
 #endif
@@ -3530,28 +3496,30 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
 
        if(!gotit) {
 
-           SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
-                          &CRT2Index,&ResIndex,HwInfo);
+          SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
+                         &CRT2Index,&ResIndex);
 
-           switch(CRT2Index) {
+          switch(CRT2Index) {
              case Panel_1024x768      : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
              case Panel_1024x768  + 32: LCDPtr = SiS_Pr->SiS_St2LCD1024x768Data;   break;
              case Panel_1280x720      :
              case Panel_1280x720  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x720Data;      break;
              case Panel_1280x768_2    : LCDPtr = SiS_Pr->SiS_ExtLCD1280x768_2Data; break;
-              case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
+             case Panel_1280x768_2+ 32: LCDPtr = SiS_Pr->SiS_StLCD1280x768_2Data;  break;
              case Panel_1280x800      :
              case Panel_1280x800  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x800Data;      break;
              case Panel_1280x800_2    :
              case Panel_1280x800_2+ 32: LCDPtr = SiS_Pr->SiS_LCD1280x800_2Data;    break;
+             case Panel_1280x854      :
+             case Panel_1280x854  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x854Data;      break;
              case Panel_1280x960      :
              case Panel_1280x960  + 32: LCDPtr = SiS_Pr->SiS_LCD1280x960Data;      break;
-              case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
-              case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
-              case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
-              case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
-              case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
-              case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
+             case Panel_1280x1024     : LCDPtr = SiS_Pr->SiS_ExtLCD1280x1024Data;  break;
+             case Panel_1280x1024 + 32: LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
+             case Panel_1400x1050     : LCDPtr = SiS_Pr->SiS_ExtLCD1400x1050Data;  break;
+             case Panel_1400x1050 + 32: LCDPtr = SiS_Pr->SiS_StLCD1400x1050Data;   break;
+             case Panel_1600x1200     : LCDPtr = SiS_Pr->SiS_ExtLCD1600x1200Data;  break;
+             case Panel_1600x1200 + 32: LCDPtr = SiS_Pr->SiS_StLCD1600x1200Data;   break;
              case Panel_1680x1050     :
              case Panel_1680x1050 + 32: LCDPtr = SiS_Pr->SiS_LCD1680x1050Data;     break;
              case 100                 : LCDPtr = SiS_Pr->SiS_NoScaleData;          break;
@@ -3559,271 +3527,340 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
              case 200                 : LCDPtr = SiS310_ExtCompaq1280x1024Data;    break;
              case 201                 : LCDPtr = SiS_Pr->SiS_St2LCD1280x1024Data;  break;
 #endif
-              default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
-           }
+             default                  : LCDPtr = SiS_Pr->SiS_ExtLCD1024x768Data;   break;
+          }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
-           xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+          xf86DrvMsg(0, X_INFO, "GetCRT2Data: Index %d ResIndex %d\n", CRT2Index, ResIndex);
+#endif
 #endif
 
-           SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
-           SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
-           SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
-           SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
-           SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
-           SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
+          SiS_Pr->SiS_RVBHCMAX  = (LCDPtr+ResIndex)->RVBHCMAX;
+          SiS_Pr->SiS_RVBHCFACT = (LCDPtr+ResIndex)->RVBHCFACT;
+          SiS_Pr->SiS_VGAHT     = (LCDPtr+ResIndex)->VGAHT;
+          SiS_Pr->SiS_VGAVT     = (LCDPtr+ResIndex)->VGAVT;
+          SiS_Pr->SiS_HT        = (LCDPtr+ResIndex)->LCDHT;
+          SiS_Pr->SiS_VT        = (LCDPtr+ResIndex)->LCDVT;
 
         }
 
        tempax = SiS_Pr->PanelXRes;
-        tempbx = SiS_Pr->PanelYRes;
+       tempbx = SiS_Pr->PanelYRes;
 
-       if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-              if(HwInfo->jChipType < SIS_315H) {
-                 if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
-                 else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-              }
-           } else {
-              if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
-              else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
-              else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
-              else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
-              else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
-              else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
-           }
-       } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960) {
-           if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
-           else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
-           else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
-       } else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-           if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
-           else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
-           else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
-        } else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) {
+       switch(SiS_Pr->SiS_LCDResInfo) {
+       case Panel_1024x768:
+          if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+             if(SiS_Pr->ChipType < SIS_315H) {
+                if     (SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+                else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+             }
+          } else {
+             if     (SiS_Pr->SiS_VGAVDE == 357) tempbx = 527;
+             else if(SiS_Pr->SiS_VGAVDE == 420) tempbx = 620;
+             else if(SiS_Pr->SiS_VGAVDE == 525) tempbx = 775;
+             else if(SiS_Pr->SiS_VGAVDE == 600) tempbx = 775;
+             else if(SiS_Pr->SiS_VGAVDE == 350) tempbx = 560;
+             else if(SiS_Pr->SiS_VGAVDE == 400) tempbx = 640;
+          }
+          break;
+       case Panel_1280x960:
+          if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 700;
+          else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 800;
+          else if(SiS_Pr->SiS_VGAVDE == 1024) tempbx = 960;
+          break;
+       case Panel_1280x1024:
+          if     (SiS_Pr->SiS_VGAVDE == 360) tempbx = 768;
+          else if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 800;
+          else if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 864;
+          break;
+       case Panel_1600x1200:
           if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-              if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
-              else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
-           }
-        }
+             if     (SiS_Pr->SiS_VGAVDE == 350)  tempbx = 875;
+             else if(SiS_Pr->SiS_VGAVDE == 400)  tempbx = 1000;
+          }
+          break;
+       }
 
-        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-           tempax = SiS_Pr->SiS_VGAHDE;
-           tempbx = SiS_Pr->SiS_VGAVDE;
-        }
+       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+          tempax = SiS_Pr->SiS_VGAHDE;
+          tempbx = SiS_Pr->SiS_VGAVDE;
+       }
 
-        SiS_Pr->SiS_HDE = tempax;
-        SiS_Pr->SiS_VDE = tempbx;
+       SiS_Pr->SiS_HDE = tempax;
+       SiS_Pr->SiS_VDE = tempbx;
      }
   }
 }
 
 static void
-SiS_GetCRT2Data(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Data(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                unsigned short RefreshRateTableIndex)
 {
 
-  if(SiS_Pr->SiS_VBType & VB_SISVB) {
+   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-        SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-     } else {
-       if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-          /* Need LVDS Data for LCD on 301B-DH */
-          SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-       } else {
-          SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
-        }
-     }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+         SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+      } else {
+        if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+           /* Need LVDS Data for LCD on 301B-DH */
+           SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+        } else {
+           SiS_GetCRT2Data301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+        }
+      }
 
-  } else {
+   } else {
 
-     SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+      SiS_GetCRT2DataLVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 
-  }
+   }
 }
 
 /*********************************************/
 /*         GET LVDS DES (SKEW) DATA          */
 /*********************************************/
 
-static void
-SiS_GetLVDSDesPtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                  USHORT RefreshRateTableIndex, USHORT *PanelIndex,
-                 USHORT *ResIndex, PSIS_HW_INFO HwInfo)
+static const struct SiS_LVDSDes *
+SiS_GetLVDSDesPtr(struct SiS_Private *SiS_Pr)
 {
-  USHORT modeflag;
+   const struct SiS_LVDSDes *PanelDesPtr = NULL;
 
-  if(ModeNo <= 0x13) {
-     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  } else {
-     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-  }
+#ifdef SIS300
+   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+
+      if(SiS_Pr->ChipType < SIS_315H) {
+        if(SiS_Pr->SiS_LCDTypeInfo == 4) {
+           if(SiS_Pr->SiS_CustomT == CUT_BARCO1366) {
+              PanelDesPtr = SiS_Pr->SiS_PanelType04_1a;
+              if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+                 PanelDesPtr = SiS_Pr->SiS_PanelType04_2a;
+              }
+            } else if(SiS_Pr->SiS_CustomT == CUT_BARCO1024) {
+              PanelDesPtr = SiS_Pr->SiS_PanelType04_1b;
+              if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+                 PanelDesPtr = SiS_Pr->SiS_PanelType04_2b;
+              }
+           }
+        }
+      }
+   }
+#endif
+   return PanelDesPtr;
+}
 
-  (*ResIndex) &= 0x1F;
-  (*PanelIndex) = 0;
+static void
+SiS_GetLVDSDesData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                   unsigned short RefreshRateTableIndex)
+{
+  unsigned short modeflag, ResIndex;
+  const struct SiS_LVDSDes *PanelDesPtr = NULL;
 
-  if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        (*PanelIndex) = 50;
-        if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) (*PanelIndex) += 2;
-        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*PanelIndex) += 1;
-        /* Nothing special needed for SOverscan    */
-        /* PALM uses NTSC data, PALN uses PAL data */
-     }
-  }
+  SiS_Pr->SiS_LCDHDES = 0;
+  SiS_Pr->SiS_LCDVDES = 0;
 
+  /* Some special cases */
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     *PanelIndex = SiS_Pr->SiS_LCDTypeInfo;
-     if(HwInfo->jChipType >= SIS_661) {
-        /* As long as we don's use the BIOS tables, we
-        * need to convert the TypeInfo as for 315 series
-        */
-        (*PanelIndex) = SiS_Pr->SiS_LCDResInfo - 1;
-     }
-     if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        (*PanelIndex) += 16;
-        if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
-           (*PanelIndex) = 32;
-           if(modeflag & HalfDCLK) (*PanelIndex)++;
+
+     /* Trumpion */
+     if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
+       if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+          if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+             SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+          }
        }
+       return;
      }
-  }
 
-  if(SiS_Pr->SiS_SetFlag & SetDOSMode) {
-     if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
-        (*ResIndex) = 7;
-        if(HwInfo->jChipType < SIS_315H) {
-           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x80) (*ResIndex)++;
-        }
+     /* 640x480 on LVDS */
+     if(SiS_Pr->ChipType < SIS_315H) {
+       if(SiS_Pr->SiS_LCDResInfo == Panel_640x480 && SiS_Pr->SiS_LCDTypeInfo == 3) {
+          SiS_Pr->SiS_LCDHDES = 8;
+          if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+          else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+          else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+          return;
+       }
      }
-  }
-}
-
-static void
-SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
-{
-  USHORT modeflag;
-  USHORT PanelIndex,ResIndex;
-  const  SiS_LVDSDesStruct *PanelDesPtr = NULL;
 
-  SiS_Pr->SiS_LCDHDES = 0;
-  SiS_Pr->SiS_LCDVDES = 0;
+  } /* LCD */
 
   if( (SiS_Pr->UseCustomMode)                   ||
       (SiS_Pr->SiS_LCDResInfo == Panel_Custom)   ||
       (SiS_Pr->SiS_CustomT == CUT_PANEL848)      ||
-      ((SiS_Pr->SiS_VBType & VB_SISVB) &&
-       (SiS_Pr->SiS_LCDInfo & DontExpandLCD) &&
-       (SiS_Pr->SiS_LCDInfo & LCDPass11)) ) {
+      (SiS_Pr->SiS_CustomT == CUT_PANEL856)      ||
+      (SiS_Pr->SiS_LCDInfo & LCDPass11) ) {
      return;
   }
 
-  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+  if(ModeNo <= 0x13) ResIndex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  else               ResIndex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+
+  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
 
 #ifdef SIS315H
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
-        /* non-pass 1:1 only, see above */
-        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
-           SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+       /* non-pass 1:1 only, see above */
+       if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+          SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+       }
+       if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+          SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
+       }
+     }
+     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+       switch(SiS_Pr->SiS_CustomT) {
+       case CUT_UNIWILL1024:
+       case CUT_UNIWILL10242:
+       case CUT_CLEVO1400:
+          if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+             SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+          }
+          break;
+       }
+       switch(SiS_Pr->SiS_LCDResInfo) {
+       case Panel_1280x1024:
+          if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
+             SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+          }
+          break;
+       case Panel_1280x800:    /* Verified for Averatec 6240 */
+       case Panel_1280x800_2:  /* Verified for Asus A4L */
+       case Panel_1280x854:    /* Not verified yet FIXME */
+          SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+          break;
+       }
+     }
+#endif
+
+  } else {
+
+     if((SiS_Pr->SiS_IF_DEF_CH70xx != 0) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+       if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+          if(ResIndex <= 3) SiS_Pr->SiS_LCDHDES = 256;
+       }
+
+     } else if((PanelDesPtr = SiS_GetLVDSDesPtr(SiS_Pr))) {
+
+       SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
+       SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
+
+     } else if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+
+       if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
+          SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
        }
        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
           SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
-       }
-     }
-     if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
-        switch(SiS_Pr->SiS_CustomT) {
-        case CUT_UNIWILL1024:
-        case CUT_UNIWILL10242:
-        case CUT_CLEVO1400:
-          if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+       } else {
+          if(SiS_Pr->ChipType < SIS_315H) {
              SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+          } else {
+             switch(SiS_Pr->SiS_LCDResInfo) {
+             case Panel_800x600:
+             case Panel_1024x768:
+             case Panel_1280x1024:
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+                break;
+             case Panel_1400x1050:
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+                break;
+             }
           }
-          break;
        }
-       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-          if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
-             SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+
+     } else {
+
+        if(SiS_Pr->ChipType < SIS_315H) {
+#ifdef SIS300
+          switch(SiS_Pr->SiS_LCDResInfo) {
+          case Panel_800x600:
+             if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+             } else {
+                SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT + 3;
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT;
+                if(SiS_Pr->SiS_VGAVDE == 400) SiS_Pr->SiS_LCDVDES -= 2;
+                else                          SiS_Pr->SiS_LCDVDES -= 4;
+             }
+             break;
+          case Panel_1024x768:
+             if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+             } else {
+                SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+                if(SiS_Pr->SiS_VGAVDE <= 400) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 8;
+                if(SiS_Pr->SiS_VGAVDE <= 350) SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 12;
+             }
+             break;
+          case Panel_1024x600:
+          default:
+             if( (SiS_Pr->SiS_VGAHDE == SiS_Pr->PanelXRes) &&
+                 (SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) ) {
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+             } else {
+                SiS_Pr->SiS_LCDHDES = SiS_Pr->PanelHT - 1;
+             }
+             break;
+          }
+
+          switch(SiS_Pr->SiS_LCDTypeInfo) {
+          case 1:
+             SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
+             break;
+          case 3: /* 640x480 only? */
+             SiS_Pr->SiS_LCDHDES = 8;
+             if     (SiS_Pr->SiS_VGAVDE >= 480) SiS_Pr->SiS_LCDVDES = 512;
+             else if(SiS_Pr->SiS_VGAVDE >= 400) SiS_Pr->SiS_LCDVDES = 436;
+             else if(SiS_Pr->SiS_VGAVDE >= 350) SiS_Pr->SiS_LCDVDES = 440;
+             break;
+          }
+#endif
+        } else {
+#ifdef SIS315H
+          switch(SiS_Pr->SiS_LCDResInfo) {
+          case Panel_1024x768:
+          case Panel_1280x1024:
+             if(SiS_Pr->SiS_VGAVDE == SiS_Pr->PanelYRes) {
+                SiS_Pr->SiS_LCDVDES = SiS_Pr->PanelVT - 1;
+             }
+             break;
+          case Panel_320x240_1:
+          case Panel_320x240_2:
+          case Panel_320x240_3:
+             SiS_Pr->SiS_LCDVDES = 524;
+             break;
           }
+#endif
        }
      }
-#endif
-
-  } else {
-
-     SiS_GetLVDSDesPtr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                       &PanelIndex, &ResIndex, HwInfo);
-
-     switch(PanelIndex) {
-       case  0: PanelDesPtr = SiS_Pr->SiS_PanelType00_1;    break;   /* ---  */
-       case  1: PanelDesPtr = SiS_Pr->SiS_PanelType01_1;    break;
-       case  2: PanelDesPtr = SiS_Pr->SiS_PanelType02_1;    break;
-       case  3: PanelDesPtr = SiS_Pr->SiS_PanelType03_1;    break;
-       case  4: PanelDesPtr = SiS_Pr->SiS_PanelType04_1;    break;
-       case  5: PanelDesPtr = SiS_Pr->SiS_PanelType05_1;    break;
-       case  6: PanelDesPtr = SiS_Pr->SiS_PanelType06_1;    break;
-       case  7: PanelDesPtr = SiS_Pr->SiS_PanelType07_1;    break;
-       case  8: PanelDesPtr = SiS_Pr->SiS_PanelType08_1;    break;
-       case  9: PanelDesPtr = SiS_Pr->SiS_PanelType09_1;    break;
-       case 10: PanelDesPtr = SiS_Pr->SiS_PanelType0a_1;    break;
-       case 11: PanelDesPtr = SiS_Pr->SiS_PanelType0b_1;    break;
-       case 12: PanelDesPtr = SiS_Pr->SiS_PanelType0c_1;    break;
-       case 13: PanelDesPtr = SiS_Pr->SiS_PanelType0d_1;    break;
-       case 14: PanelDesPtr = SiS_Pr->SiS_PanelType0e_1;    break;
-       case 15: PanelDesPtr = SiS_Pr->SiS_PanelType0f_1;    break;
-       case 16: PanelDesPtr = SiS_Pr->SiS_PanelType00_2;    break;    /* --- */
-       case 17: PanelDesPtr = SiS_Pr->SiS_PanelType01_2;    break;
-       case 18: PanelDesPtr = SiS_Pr->SiS_PanelType02_2;    break;
-       case 19: PanelDesPtr = SiS_Pr->SiS_PanelType03_2;    break;
-       case 20: PanelDesPtr = SiS_Pr->SiS_PanelType04_2;    break;
-       case 21: PanelDesPtr = SiS_Pr->SiS_PanelType05_2;    break;
-       case 22: PanelDesPtr = SiS_Pr->SiS_PanelType06_2;    break;
-       case 23: PanelDesPtr = SiS_Pr->SiS_PanelType07_2;    break;
-       case 24: PanelDesPtr = SiS_Pr->SiS_PanelType08_2;    break;
-       case 25: PanelDesPtr = SiS_Pr->SiS_PanelType09_2;    break;
-       case 26: PanelDesPtr = SiS_Pr->SiS_PanelType0a_2;    break;
-       case 27: PanelDesPtr = SiS_Pr->SiS_PanelType0b_2;    break;
-       case 28: PanelDesPtr = SiS_Pr->SiS_PanelType0c_2;    break;
-       case 29: PanelDesPtr = SiS_Pr->SiS_PanelType0d_2;    break;
-       case 30: PanelDesPtr = SiS_Pr->SiS_PanelType0e_2;    break;
-       case 31: PanelDesPtr = SiS_Pr->SiS_PanelType0f_2;    break;
-       case 32: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_1;    break;    /* pass 1:1 */
-       case 33: PanelDesPtr = SiS_Pr->SiS_PanelTypeNS_2;    break;
-       case 50: PanelDesPtr = SiS_Pr->SiS_CHTVUNTSCDesData; break;    /* TV */
-       case 51: PanelDesPtr = SiS_Pr->SiS_CHTVONTSCDesData; break;
-       case 52: PanelDesPtr = SiS_Pr->SiS_CHTVUPALDesData;  break;
-       case 53: PanelDesPtr = SiS_Pr->SiS_CHTVOPALDesData;  break;
-       default: return;
-     }
-
-     SiS_Pr->SiS_LCDHDES = (PanelDesPtr+ResIndex)->LCDHDES;
-     SiS_Pr->SiS_LCDVDES = (PanelDesPtr+ResIndex)->LCDVDES;
 
      if((ModeNo <= 0x13) && (SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
-        modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-        if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+       modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+       if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
           if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 632;
-        } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
-           if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
-              if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
-                if(HwInfo->jChipType < SIS_315H) {
+       } else if(!(SiS_Pr->SiS_SetFlag & SetDOSMode)) {
+          if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+             if(SiS_Pr->SiS_LCDResInfo >= Panel_1024x768) {
+                if(SiS_Pr->ChipType < SIS_315H) {
                    if(!(modeflag & HalfDCLK)) SiS_Pr->SiS_LCDHDES = 320;
                 } else {
-                   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
-                    if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
+#ifdef SIS315H
+                   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  SiS_Pr->SiS_LCDHDES = 480;
+                   if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 804;
                    if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 704;
-                    if(!(modeflag & HalfDCLK)) {
-                       SiS_Pr->SiS_LCDHDES = 320;
-                      if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
+                   if(!(modeflag & HalfDCLK)) {
+                      SiS_Pr->SiS_LCDHDES = 320;
+                      if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) SiS_Pr->SiS_LCDHDES = 632;
                       if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) SiS_Pr->SiS_LCDHDES = 542;
-                    }
-                 }
-              }
-           }
-        }
+                   }
+#endif
+                }
+             }
+          }
+       }
      }
   }
 }
@@ -3832,54 +3869,90 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
 /*           DISABLE VIDEO BRIDGE            */
 /*********************************************/
 
+#ifdef SIS315H
+static int
+SiS_HandlePWD(struct SiS_Private *SiS_Pr)
+{
+   int ret = 0;
+#ifdef SET_PWD
+   unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
+   unsigned char  drivermode = SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40;
+   unsigned short temp;
+
+   if( (SiS_Pr->SiS_VBType & VB_SISPWD) &&
+       (romptr)                                &&
+       (SiS_Pr->SiS_PWDOffset) ) {
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2b,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 0]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2c,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 1]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2d,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 2]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2e,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 3]);
+      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2f,ROMAddr[romptr + SiS_Pr->SiS_PWDOffset + 4]);
+      temp = 0x00;
+      if((ROMAddr[romptr + 2] & (0x06 << 1)) && !drivermode) {
+         temp = 0x80;
+        ret = 1;
+      }
+      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x27,0x7f,temp);
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+      xf86DrvMsg(0, 0, "Setting PWD %x\n", temp);
+#endif
+#endif
+   }
+#endif
+   return ret;
+}
+#endif
+
 /* NEVER use any variables (VBInfo), this will be called
  * from outside the context of modeswitch!
  * MUST call getVBType before calling this
  */
 void
-SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_DisableBridge(struct SiS_Private *SiS_Pr)
 {
 #ifdef SIS315H
-  USHORT tempah,pushax=0,modenum;
+  unsigned short tempah, pushax=0, modenum;
 #endif
-  USHORT temp=0;
+  unsigned short temp=0;
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {           /* ===== For 30xB/C/LV ===== */
 
-        if(HwInfo->jChipType < SIS_315H) {
+       if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300     /* 300 series */
 
-          if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-                SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+          if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+             if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+                SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
              } else {
-                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
+                SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
              }
-             SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+             SiS_PanelDelay(SiS_Pr, 3);
           }
           if(SiS_Is301B(SiS_Pr)) {
              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
              SiS_ShortDelay(SiS_Pr,1);
-           }
+          }
           SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
           SiS_DisplayOff(SiS_Pr);
           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-          SiS_UnLockCRT2(SiS_Pr,HwInfo);
-          if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+          SiS_UnLockCRT2(SiS_Pr);
+          if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) {
              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
           }
-          if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-              (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-             SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+          if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+              (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+             SiS_PanelDelay(SiS_Pr, 2);
+             if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+                SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
              } else {
-                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+                SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
              }
           }
 
@@ -3889,130 +3962,127 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
 #ifdef SIS315H    /* 315 series */
 
+          int didpwd = 0;
           BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
                              (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
 
           modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
 
-           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+          if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
 
 #ifdef SET_EMI
-             if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+             if(SiS_Pr->SiS_VBType & VB_SISEMI) {
                 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
                 }
              }
 #endif
-             if( (modenum <= 0x13)                  ||
-                 (SiS_IsVAMode(SiS_Pr,HwInfo))      ||
-                 (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
-                SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-                if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+
+             didpwd = SiS_HandlePWD(SiS_Pr);
+
+             if( (modenum <= 0x13)           ||
+                 (SiS_IsVAMode(SiS_Pr))      ||
+                 (!(SiS_IsDualEdge(SiS_Pr))) ) {
+                if(!didpwd) {
+                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfe);
+                   if(custom1) SiS_PanelDelay(SiS_Pr, 3);
+                } else {
+                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xfc);
+                }
              }
 
              if(!custom1) {
                 SiS_DDC2Delay(SiS_Pr,0xff00);
                 SiS_DDC2Delay(SiS_Pr,0xe000);
-                SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-                 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+                SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+                pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
                 if(IS_SIS740) {
                    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
                 }
-                SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+                SiS_PanelDelay(SiS_Pr, 3);
              }
 
-           }
+          }
 
-          if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
-             if(HwInfo->jChipType < SIS_340) {
-                tempah = 0xef;
-                if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
-                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-             }
+          if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+             /* if(SiS_Pr->ChipType < SIS_340) {*/
+                tempah = 0xef;
+                if(SiS_IsVAMode(SiS_Pr)) tempah = 0xf7;
+                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+             /*}*/
           }
 
-          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+          if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
           }
 
           tempah = 0x3f;
-          if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+          if(SiS_IsDualEdge(SiS_Pr)) {
              tempah = 0x7f;
-             if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
+             if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0xbf;
           }
           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-           if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-             ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+          if((SiS_IsVAMode(SiS_Pr)) ||
+             ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
 
              SiS_DisplayOff(SiS_Pr);
-             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-                SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+             if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+                SiS_PanelDelay(SiS_Pr, 2);
              }
              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
 
           }
 
-          if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
-             ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+          if((!(SiS_IsVAMode(SiS_Pr))) ||
+             ((SiS_Pr->SiS_VBType & VB_SISLVDS) && (modenum <= 0x13))) {
 
-             if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
+             if(!(SiS_IsDualEdge(SiS_Pr))) {
                 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
                 SiS_DisplayOff(SiS_Pr);
              }
              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
 
-             if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-                SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+             if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+                SiS_PanelDelay(SiS_Pr, 2);
              }
 
              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
              temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
              SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 
           }
 
-          if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+          if(SiS_IsNotM650orLater(SiS_Pr)) {
              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
           }
 
-          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-
-             if(!custom1) {
-
-                if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-                   if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
-                      if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
-                         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-                       }
-                    }
-                }
-
-                SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+          if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
 
-                if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-                   if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
-                      SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
-                   }
-                }
+             if( (!(SiS_IsVAMode(SiS_Pr)))  &&
+                 (!(SiS_CRT2IsLCD(SiS_Pr))) &&
+                 (!(SiS_IsDualEdge(SiS_Pr))) ) {
 
-             } else {
+                if(custom1) SiS_PanelDelay(SiS_Pr, 2);
+                if(!didpwd) {
+                   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+                }
+                if(custom1) SiS_PanelDelay(SiS_Pr, 4);
+             }
 
-                if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-                   (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
-                   if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
-                      (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
-                      SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-                      SiS_PanelDelay(SiS_Pr, HwInfo, 4);
+             if(!custom1) {
+                SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+                if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+                   if(SiS_IsVAorLCD(SiS_Pr)) {
+                      SiS_PanelDelayLoop(SiS_Pr, 3, 20);
                    }
                 }
-
              }
-           }
+
+          }
 
 #endif /* SIS315H */
 
@@ -4020,36 +4090,36 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
      } else {     /* ============ For 301 ================ */
 
-        if(HwInfo->jChipType < SIS_315H) {
+        if(SiS_Pr->ChipType < SIS_315H) {
 #ifdef SIS300
-           if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-             SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+          if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+             SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+             SiS_PanelDelay(SiS_Pr, 3);
           }
 #endif
        }
 
-        SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
-        SiS_DisplayOff(SiS_Pr);
+       SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);           /* disable VB */
+       SiS_DisplayOff(SiS_Pr);
 
-        if(HwInfo->jChipType >= SIS_315H) {
-           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+       if(SiS_Pr->ChipType >= SIS_315H) {
+          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
        }
 
-        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
+       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);                /* disable lock mode */
 
-       if(HwInfo->jChipType >= SIS_315H) {
-            temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+       if(SiS_Pr->ChipType >= SIS_315H) {
+           temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
        } else {
 #ifdef SIS300
-            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
-           if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-               (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
-               SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-               SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);            /* disable CRT2 */
+           if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+               (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+               SiS_PanelDelay(SiS_Pr, 2);
+               SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
            }
 #endif
        }
@@ -4058,34 +4128,34 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
   } else {     /* ============ For LVDS =============*/
 
-    if(HwInfo->jChipType < SIS_315H) {
+    if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300  /* 300 series */
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-          SiS_SetCH700x(SiS_Pr,0x090E);
+          SiS_SetCH700x(SiS_Pr,0x0E,0x09);
        }
 
-       if(HwInfo->jChipType == SIS_730) {
+       if(SiS_Pr->ChipType == SIS_730) {
           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
-             SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+             SiS_WaitVBRetrace(SiS_Pr);
           }
-          if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-             SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+          if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+             SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+             SiS_PanelDelay(SiS_Pr, 3);
           }
        } else {
           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x08)) {
              if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-                if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-                    SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+                if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+                   SiS_WaitVBRetrace(SiS_Pr);
                    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x1c)) {
                       SiS_DisplayOff(SiS_Pr);
-                   }
-                   SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-                   SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-                 }
-              }
+                   }
+                   SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+                   SiS_PanelDelay(SiS_Pr, 3);
+                }
+             }
           }
        }
 
@@ -4094,14 +4164,14 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
 
        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-       SiS_UnLockCRT2(SiS_Pr,HwInfo);
+       SiS_UnLockCRT2(SiS_Pr);
        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
 
-       if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-           (!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) ) {
-          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+       if( (!(SiS_CRT2IsLCD(SiS_Pr))) ||
+           (!(SiS_CR36BIOSWord23d(SiS_Pr))) ) {
+          SiS_PanelDelay(SiS_Pr, 2);
+          SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
        }
 
 #endif  /* SIS300 */
@@ -4110,113 +4180,113 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
 #ifdef SIS315H /* 315 series */
 
-        if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-          if(HwInfo->jChipType < SIS_340) {
-              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
-          }
-        }
+       if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+          /*if(SiS_Pr->ChipType < SIS_340) { */ /* XGI needs this */
+             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+          /* } */
+       }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 
-          if(HwInfo->jChipType == SIS_740) {
+          if(SiS_Pr->ChipType == SIS_740) {
              temp = SiS_GetCH701x(SiS_Pr,0x61);
              if(temp < 1) {
-                SiS_SetCH701x(SiS_Pr,0xac76);
-                SiS_SetCH701x(SiS_Pr,0x0066);
+                SiS_SetCH701x(SiS_Pr,0x76,0xac);
+                SiS_SetCH701x(SiS_Pr,0x66,0x00);
              }
 
-             if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-                 (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
-                SiS_SetCH701x(SiS_Pr,0x3e49);
+             if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+                 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+                SiS_SetCH701x(SiS_Pr,0x49,0x3e);
              }
           }
 
-          if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-              (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
+          if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+              (SiS_IsVAMode(SiS_Pr)) ) {
              SiS_Chrontel701xBLOff(SiS_Pr);
-             SiS_Chrontel701xOff(SiS_Pr,HwInfo);
+             SiS_Chrontel701xOff(SiS_Pr);
           }
 
-          if(HwInfo->jChipType != SIS_740) {
-             if( (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-                 (SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) ) {
-                SiS_SetCH701x(SiS_Pr,0x0149);
-             }
+          if(SiS_Pr->ChipType != SIS_740) {
+             if( (!(SiS_IsDualEdge(SiS_Pr))) ||
+                 (SiS_IsTVOrYPbPrOrScart(SiS_Pr)) ) {
+                SiS_SetCH701x(SiS_Pr,0x49,0x01);
+             }
           }
 
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-          SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+          SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x08);
+          SiS_PanelDelay(SiS_Pr, 3);
        }
 
        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-           (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-           (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo))) ) {
+           (!(SiS_IsDualEdge(SiS_Pr))) ||
+           (!(SiS_IsTVOrYPbPrOrScart(SiS_Pr))) ) {
           SiS_DisplayOff(SiS_Pr);
        }
 
        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-           (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-           (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+           (!(SiS_IsDualEdge(SiS_Pr))) ||
+           (!(SiS_IsVAMode(SiS_Pr))) ) {
           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
        }
 
-       if(HwInfo->jChipType == SIS_740) {
+       if(SiS_Pr->ChipType == SIS_740) {
           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
        }
 
        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
 
        if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-           (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-           (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+           (!(SiS_IsDualEdge(SiS_Pr))) ||
+           (!(SiS_IsVAMode(SiS_Pr))) ) {
           SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+          if(SiS_CRT2IsLCD(SiS_Pr)) {
              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
-             if(HwInfo->jChipType == SIS_550) {
-                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
-                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
+             if(SiS_Pr->ChipType == SIS_550) {
+                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xbf);
+                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xef);
              }
           }
        } else {
-          if(HwInfo->jChipType == SIS_740) {
-             if(SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) {
-                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
+          if(SiS_Pr->ChipType == SIS_740) {
+             if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+                SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
              }
-          } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
+          } else if(SiS_IsVAMode(SiS_Pr)) {
              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1e,0xdf);
           }
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-          if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+          if(SiS_IsDualEdge(SiS_Pr)) {
              /* SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xff); */
           } else {
              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x13,0xfb);
           }
        }
 
-       SiS_UnLockCRT2(SiS_Pr,HwInfo);
+       SiS_UnLockCRT2(SiS_Pr);
 
-       if(HwInfo->jChipType == SIS_550) {
+       if(SiS_Pr->ChipType == SIS_550) {
           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80); /* DirectDVD PAL?*/
           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40); /* VB clock / 4 ? */
        } else if( (SiS_Pr->SiS_IF_DEF_CH70xx == 0)   ||
-                  (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-                  (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
+                  (!(SiS_IsDualEdge(SiS_Pr))) ||
+                  (!(SiS_IsVAMode(SiS_Pr))) ) {
           SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
        }
 
         if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-             if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-                SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+          if(SiS_CRT2IsLCD(SiS_Pr)) {
+             if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+                SiS_PanelDelay(SiS_Pr, 2);
+                SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x04);
              }
           }
         }
@@ -4237,78 +4307,81 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
  * from outside the context of a mode switch!
  * MUST call getVBType before calling this
  */
-static void
-SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_EnableBridge(struct SiS_Private *SiS_Pr)
 {
-  USHORT temp=0,tempah;
+  unsigned short temp=0, tempah;
 #ifdef SIS315H
-  USHORT temp1,pushax=0;
+  unsigned short temp1, pushax=0;
   BOOLEAN delaylong = FALSE;
 #endif
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ====== For 301B et al  ====== */
+    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {            /* ====== For 301B et al  ====== */
 
-      if(HwInfo->jChipType < SIS_315H) {
+      if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300     /* 300 series */
 
-        if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        if(SiS_CRT2IsLCD(SiS_Pr)) {
+           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
            } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-              SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
+              SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
            }
-           if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
-              if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
-                 SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+           if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_NoLCD)) {
+              if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+                 SiS_PanelDelay(SiS_Pr, 0);
               }
            }
         }
 
         if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
-           (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
+           (SiS_CRT2IsLCD(SiS_Pr))) {
 
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* Enable CRT2 */
-            SiS_DisplayOn(SiS_Pr);
-           SiS_UnLockCRT2(SiS_Pr,HwInfo);
+           SiS_DisplayOn(SiS_Pr);
+           SiS_UnLockCRT2(SiS_Pr);
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
            if(SiS_BridgeInSlavemode(SiS_Pr)) {
-              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
-           } else {
-              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
-            }
+              SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+           } else {
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+           }
            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
               if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-                 if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-                    SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-                  }
-                 SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
-               }
+                 if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+                    SiS_PanelDelay(SiS_Pr, 1);
+                 }
+                 SiS_WaitVBRetrace(SiS_Pr);
+                 SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+              }
            }
 
         } else {
 
            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-            if(SiS_BridgeInSlavemode(SiS_Pr)) {
-               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-               if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
-            }
-            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+           if(SiS_BridgeInSlavemode(SiS_Pr)) {
+              tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+              if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+           }
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
            SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
            SiS_DisplayOn(SiS_Pr);
-           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-              if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-                 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-                    if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-                       SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-                     }
+           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+              if(SiS_CRT2IsLCD(SiS_Pr)) {
+                 if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+                    if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+                       SiS_PanelDelay(SiS_Pr, 1);
+                    }
                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-                 }
+                 }
               }
            }
 
@@ -4322,31 +4395,32 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 #ifdef SIS315H    /* 315 series */
 
 #ifdef SET_EMI
-        UCHAR   r30=0, r31=0, r32=0, r33=0, cr36=0;
-        /* USHORT  emidelay=0; */
+        unsigned char   r30=0, r31=0, r32=0, r33=0, cr36=0;
+        int didpwd = 0;
+        /* unsigned short  emidelay=0; */
 #endif
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
 #ifdef SET_EMI
-           if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+           if(SiS_Pr->SiS_VBType & VB_SISEMI) {
               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
            }
 #endif
         }
 
-         if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
-           if(HwInfo->jChipType < SIS_340) {
+        if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+           /*if(SiS_Pr->ChipType < SIS_340) { */
               tempah = 0x10;
-              if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-                 if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-                 else                              tempah = 0x08;
+              if(SiS_LCDAEnabled(SiS_Pr)) {
+                 if(SiS_TVEnabled(SiS_Pr)) tempah = 0x18;
+                 else                      tempah = 0x08;
               }
               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-           }
+           /*}*/
         }
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
 
            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
            SiS_DisplayOff(SiS_Pr);
@@ -4355,42 +4429,51 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
            }
 
-           if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
-               if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
-                 SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-                 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-                 SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-                 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-                    SiS_GenericDelay(SiS_Pr, 0x4500);
+           didpwd = SiS_HandlePWD(SiS_Pr);
+
+           if(SiS_IsVAorLCD(SiS_Pr)) {
+              if(!didpwd) {
+                 if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+                    SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+                    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+                    SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+                    if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+                       SiS_GenericDelay(SiS_Pr, 17664);
+                    }
+                 }
+              } else {
+                 SiS_PanelDelayLoop(SiS_Pr, 3, 2);
+                 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+                    SiS_GenericDelay(SiS_Pr, 17664);
                  }
               }
            }
 
            if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
-               SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+              SiS_PanelDelayLoop(SiS_Pr, 3, 10);
               delaylong = TRUE;
            }
 
         }
 
-        if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
+        if(!(SiS_IsVAMode(SiS_Pr))) {
 
-            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+           temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
            if(SiS_BridgeInSlavemode(SiS_Pr)) {
-               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-               if(!(tempah & SetCRT2ToRAMDAC)) {
-                 if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
+              tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+              if(!(tempah & SetCRT2ToRAMDAC)) {
+                 if(!(SiS_LCDAEnabled(SiS_Pr))) temp |= 0x20;
               }
-            }
-            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+           }
+           SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
            SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
 
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
 
-           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-              SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+           if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+              SiS_PanelDelay(SiS_Pr, 2);
            }
 
         } else {
@@ -4402,38 +4485,48 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
 
+        if(SiS_Pr->SiS_VBType & VB_SISPOWER) {
+           if( (SiS_LCDAEnabled(SiS_Pr)) ||
+               (SiS_CRT2IsLCD(SiS_Pr)) ) {
+              /* Enable "LVDS PLL power on" (even on 301C) */
+              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);
+              /* Enable "LVDS Driver Power on" (even on 301C) */
+              SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x7f);
+           }
+        }
+
         tempah = 0xc0;
-        if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+        if(SiS_IsDualEdge(SiS_Pr)) {
            tempah = 0x80;
-           if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
+           if(!(SiS_IsVAMode(SiS_Pr))) tempah = 0x40;
         }
-         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+        if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
 
-           SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+           SiS_PanelDelay(SiS_Pr, 2);
 
            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
 
            if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
 #ifdef SET_EMI
-              if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-                 SiS_GenericDelay(SiS_Pr, 0x500);
+              if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+                 SiS_GenericDelay(SiS_Pr, 2048);
               }
 #endif
               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
 
-              if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+              if(SiS_Pr->SiS_VBType & VB_SISEMI) {
 #ifdef SET_EMI
                  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
 
                  if(SiS_Pr->SiS_ROMNew) {
-                    UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-                    USHORT romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
+                    unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+                    unsigned short romptr = GetLCDStructPtr661_2(SiS_Pr);
                     if(romptr) {
-                       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
+                       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
                        SiS_Pr->EMI_30 = 0;
                        SiS_Pr->EMI_31 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 0];
                        SiS_Pr->EMI_32 = ROMAddr[romptr + SiS_Pr->SiS_EMIOffset + 1];
@@ -4511,21 +4604,21 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
                  if(!SiS_Pr->OverruleEMI) {
 #ifdef COMPAL_HACK
                     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
-                       if((cr36 & 0x0f) == 0x09) {
+                       if((cr36 & 0x0f) == 0x09) {
                           r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
                        }
                     }
 #endif
 #ifdef COMPAQ_HACK
                     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-                       if((cr36 & 0x0f) == 0x03) {
+                       if((cr36 & 0x0f) == 0x03) {
                           r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
                        }
                     }
 #endif
 #ifdef ASUS_HACK
                     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-                       if((cr36 & 0x0f) == 0x02) {
+                       if((cr36 & 0x0f) == 0x02) {
                           /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
                           /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
                           /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
@@ -4533,11 +4626,11 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
                        }
                     }
 #endif
-                 }
+                 }
 
                  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
                     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20); /* Reset */
-                    SiS_GenericDelay(SiS_Pr, 0x500);
+                    SiS_GenericDelay(SiS_Pr, 2048);
                  }
                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
@@ -4547,36 +4640,44 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
                  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
 
 #ifdef SET_EMI
-                 if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) ||
-                     (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-                    if(r30 & 0x40) {
-                       SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+                 if( (SiS_LCDAEnabled(SiS_Pr)) ||
+                     (SiS_CRT2IsLCD(SiS_Pr)) ) {
+                    if(r30 & 0x40) {
+                       /*SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x2a,0x80);*/
+                       SiS_PanelDelayLoop(SiS_Pr, 3, 5);
                        if(delaylong) {
-                          SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+                          SiS_PanelDelayLoop(SiS_Pr, 3, 5);
                           delaylong = FALSE;
                        }
-                       SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+                       SiS_WaitVBRetrace(SiS_Pr);
+                       SiS_WaitVBRetrace(SiS_Pr);
                        if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-                          SiS_GenericDelay(SiS_Pr, 0x500);
+                          SiS_GenericDelay(SiS_Pr, 1280);
                        }
-                       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
-                    }
+                       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   /* Enable */
+                       /*SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x2a,0x7f);*/
+                    }
                  }
 #endif
               }
            }
 
-           if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-              if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
-                 SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+           if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+              if(SiS_IsVAorLCD(SiS_Pr)) {
+                 SiS_PanelDelayLoop(SiS_Pr, 3, 10);
                  if(delaylong) {
-                    SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+                    SiS_PanelDelayLoop(SiS_Pr, 3, 10);
                  }
-                  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-                    SiS_GenericDelay(SiS_Pr, 0x500);
+                 SiS_WaitVBRetrace(SiS_Pr);
+                 if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+                    SiS_GenericDelay(SiS_Pr, 2048);
+                    SiS_WaitVBRetrace(SiS_Pr);
+                 }
+                 if(!didpwd) {
+                    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+                 } else {
+                    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x03);
                  }
-                 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
               }
            }
 
@@ -4586,7 +4687,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
         }
 
-        if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+        if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
         }
 
@@ -4596,26 +4697,26 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
     } else {   /* ============  For 301 ================ */
 
-       if(HwInfo->jChipType < SIS_315H) {
-          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
-            SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+       if(SiS_Pr->ChipType < SIS_315H) {
+         if(SiS_CRT2IsLCD(SiS_Pr)) {
+            SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+            SiS_PanelDelay(SiS_Pr, 0);
          }
        }
 
        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
        if(SiS_BridgeInSlavemode(SiS_Pr)) {
-          tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-          if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
+         tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+         if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
        }
        SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                  /* enable CRT2 */
 
-       if(HwInfo->jChipType >= SIS_315H) {
-          temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-          if(!(temp & 0x80)) {
-             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
+       if(SiS_Pr->ChipType >= SIS_315H) {
+         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
+         if(!(temp & 0x80)) {
+            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);         /* BVBDOENABLE=1 */
          }
        }
 
@@ -4623,15 +4724,15 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
        SiS_VBLongWait(SiS_Pr);
        SiS_DisplayOn(SiS_Pr);
-       if(HwInfo->jChipType >= SIS_315H) {
-          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+       if(SiS_Pr->ChipType >= SIS_315H) {
+         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
        }
        SiS_VBLongWait(SiS_Pr);
 
-       if(HwInfo->jChipType < SIS_315H) {
-          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-            SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-             SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+       if(SiS_Pr->ChipType < SIS_315H) {
+         if(SiS_CRT2IsLCD(SiS_Pr)) {
+            SiS_PanelDelay(SiS_Pr, 1);
+            SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
          }
        }
 
@@ -4639,49 +4740,49 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
   } else {   /* =================== For LVDS ================== */
 
-    if(HwInfo->jChipType < SIS_315H) {
+    if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300    /* 300 series */
 
-       if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-          if(HwInfo->jChipType == SIS_730) {
-            SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-            SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-            SiS_PanelDelay(SiS_Pr, HwInfo, 1);
+       if(SiS_CRT2IsLCD(SiS_Pr)) {
+         if(SiS_Pr->ChipType == SIS_730) {
+            SiS_PanelDelay(SiS_Pr, 1);
+            SiS_PanelDelay(SiS_Pr, 1);
+            SiS_PanelDelay(SiS_Pr, 1);
          }
-          SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
-         if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
-            SiS_PanelDelay(SiS_Pr, HwInfo, 0);
+         SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+         if(!(SiS_CR36BIOSWord23d(SiS_Pr))) {
+            SiS_PanelDelay(SiS_Pr, 0);
          }
        }
 
        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
        SiS_DisplayOn(SiS_Pr);
-       SiS_UnLockCRT2(SiS_Pr,HwInfo);
+       SiS_UnLockCRT2(SiS_Pr);
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
        if(SiS_BridgeInSlavemode(SiS_Pr)) {
-         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
        } else {
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+         SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
-          if(!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
-            SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-            SiS_SetCH700x(SiS_Pr,0x0B0E);
-          }
+         if(!(SiS_CRT2IsLCD(SiS_Pr))) {
+            SiS_WaitVBRetrace(SiS_Pr);
+            SiS_SetCH700x(SiS_Pr,0x0E,0x0B);
+         }
        }
 
-       if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-             if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-               if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-                  SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-                  SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-               }
-               SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-                SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
-             }
+       if(SiS_CRT2IsLCD(SiS_Pr)) {
+         if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+            if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+               if(!(SiS_CR36BIOSWord23b(SiS_Pr))) {
+                  SiS_PanelDelay(SiS_Pr, 1);
+                  SiS_PanelDelay(SiS_Pr, 1);
+               }
+               SiS_WaitVBRetrace(SiS_Pr);
+               SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
+            }
          }
        }
 
@@ -4691,94 +4792,94 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
 #ifdef SIS315H    /* 315 series */
 
-       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-          if(HwInfo->jChipType < SIS_340) {
-             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
-         }
+       if(!(SiS_IsNotM650orLater(SiS_Pr))) {
+         /*if(SiS_Pr->ChipType < SIS_340) {*/  /* XGI needs this */
+            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+         /*}*/
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-         if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-            SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
-            SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-          }
+         if(SiS_CRT2IsLCD(SiS_Pr)) {
+            SiS_SetRegSR11ANDOR(SiS_Pr,0xFB,0x00);
+            SiS_PanelDelay(SiS_Pr, 0);
+         }
        }
 
        SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-       SiS_UnLockCRT2(SiS_Pr,HwInfo);
+       SiS_UnLockCRT2(SiS_Pr);
 
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0xf7);
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-          temp = SiS_GetCH701x(SiS_Pr,0x66);
+         temp = SiS_GetCH701x(SiS_Pr,0x66);
          temp &= 0x20;
          SiS_Chrontel701xBLOff(SiS_Pr);
        }
 
-       if(HwInfo->jChipType != SIS_550) {
-          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+       if(SiS_Pr->ChipType != SIS_550) {
+         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
        }
 
-       if(HwInfo->jChipType == SIS_740) {
-          if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-             if(SiS_IsLCDOrLCDA(SiS_Pr, HwInfo)) {
-               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+       if(SiS_Pr->ChipType == SIS_740) {
+         if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+            if(SiS_IsLCDOrLCDA(SiS_Pr)) {
+               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
             }
          }
        }
 
        temp1 = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
        if(!(temp1 & 0x80)) {
-          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
+         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-          if(temp) {
-            SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
+         if(temp) {
+            SiS_Chrontel701xBLOn(SiS_Pr);
          }
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-          if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+         if(SiS_CRT2IsLCD(SiS_Pr)) {
             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
-            if(HwInfo->jChipType == SIS_550) {
+            if(SiS_Pr->ChipType == SIS_550) {
                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x40);
                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x10);
             }
          }
-       } else if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-          if(HwInfo->jChipType != SIS_740) {
-             SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
+       } else if(SiS_IsVAMode(SiS_Pr)) {
+         if(SiS_Pr->ChipType != SIS_740) {
+            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1E,0x20);
          }
        }
 
-       if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+       if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+         SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-                 if(SiS_IsTVOrYPbPrOrScart(SiS_Pr,HwInfo)) {
-             SiS_Chrontel701xOn(SiS_Pr,HwInfo);
-          }
-          if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-             (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
-             SiS_ChrontelDoSomething1(SiS_Pr,HwInfo);
-          }
+         if(SiS_IsTVOrYPbPrOrScart(SiS_Pr)) {
+            SiS_Chrontel701xOn(SiS_Pr);
+         }
+         if( (SiS_IsVAMode(SiS_Pr)) ||
+             (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+            SiS_ChrontelDoSomething1(SiS_Pr);
+         }
        }
 
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-                 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-            if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-                (SiS_IsLCDOrLCDA(SiS_Pr,HwInfo)) ) {
-               SiS_Chrontel701xBLOn(SiS_Pr, HwInfo);
-               SiS_ChrontelInitTVVSync(SiS_Pr,HwInfo);
-             }
-                 }
+         if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+            if( (SiS_IsVAMode(SiS_Pr)) ||
+                (SiS_IsLCDOrLCDA(SiS_Pr)) ) {
+               SiS_Chrontel701xBLOn(SiS_Pr);
+               SiS_ChrontelInitTVVSync(SiS_Pr);
+            }
+         }
        } else if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
-                 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-            if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-               SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-               SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+         if(!(SiS_WeHaveBacklightCtrl(SiS_Pr))) {
+            if(SiS_CRT2IsLCD(SiS_Pr)) {
+               SiS_PanelDelay(SiS_Pr, 1);
+               SiS_SetRegSR11ANDOR(SiS_Pr,0xF7,0x00);
             }
          }
        }
@@ -4797,243 +4898,204 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
 /* Set CRT2 OFFSET / PITCH */
 static void
-SiS_SetCRT2Offset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                 USHORT RRTI, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Offset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RRTI)
 {
-  USHORT offset;
-  UCHAR temp;
+   unsigned short offset;
+   unsigned char  temp;
 
-  if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
+   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) return;
 
-  offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI,HwInfo);
+   offset = SiS_GetOffset(SiS_Pr,ModeNo,ModeIdIndex,RRTI);
 
-  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
-     (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
-     offset >>= 1;
-  }
+   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
+   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,(offset & 0xFF));
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,(offset >> 8));
-  temp = (UCHAR)(((offset >> 3) & 0xFF) + 1);
-  if(offset % 8) temp++;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
+   temp = (unsigned char)(((offset >> 3) & 0xFF) + 1);
+   if(offset & 0x07) temp++;
+   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,temp);
 }
 
 /* Set CRT2 sync and PanelLink mode */
 static void
-SiS_SetCRT2Sync(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT RefreshRateTableIndex,
-                PSIS_HW_INFO HwInfo)
+SiS_SetCRT2Sync(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RefreshRateTableIndex)
 {
-  USHORT tempah=0,tempbl,infoflag;
+   unsigned short tempah=0, tempbl, infoflag;
 
-  tempbl = 0xC0;
+   tempbl = 0xC0;
 
-  if(SiS_Pr->UseCustomMode) {
-     infoflag = SiS_Pr->CInfoFlag;
-  } else {
-     infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-  }
+   if(SiS_Pr->UseCustomMode) {
+      infoflag = SiS_Pr->CInfoFlag;
+   } else {
+      infoflag = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+   }
 
-  if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {                                   /* LVDS */
+   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {                                  /* LVDS */
 
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        tempah = 0;
-     } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
-        tempah = SiS_Pr->SiS_LCDInfo;
-     } else tempah = infoflag >> 8;
-     tempah &= 0xC0;
-     tempah |= 0x20;
-     if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
-           (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-          tempah |= 0xf0;
-        }
-       if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
-            (SiS_Pr->SiS_IF_DEF_DSTN) ||
-            (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
-            (SiS_Pr->SiS_CustomT == CUT_PANEL848) ) {
-           tempah |= 0x30;
-        }
-     }
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(HwInfo->jChipType >= SIS_315H) {
-           tempah >>= 3;
-          tempah &= 0x18;
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
-          /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
-        } else {
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
-        }
-     } else {
-        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-     }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+        tempah = 0;
+      } else if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->SiS_LCDInfo & LCDSync)) {
+        tempah = SiS_Pr->SiS_LCDInfo;
+      } else tempah = infoflag >> 8;
+      tempah &= 0xC0;
+      tempah |= 0x20;
+      if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+        if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+           (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+           tempah |= 0xf0;
+        }
+        if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+            (SiS_Pr->SiS_IF_DEF_DSTN) ||
+            (SiS_Pr->SiS_IF_DEF_TRUMPION) ||
+            (SiS_Pr->SiS_CustomT == CUT_PANEL848) ||
+            (SiS_Pr->SiS_CustomT == CUT_PANEL856) ) {
+           tempah |= 0x30;
+        }
+        if( (SiS_Pr->SiS_IF_DEF_FSTN) ||
+            (SiS_Pr->SiS_IF_DEF_DSTN) ) {
+           tempah &= ~0xc0;
+        }
+      }
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+        if(SiS_Pr->ChipType >= SIS_315H) {
+           tempah >>= 3;
+           tempah &= 0x18;
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xE7,tempah);
+           /* Don't care about 12/18/24 bit mode - TV is via VGA, not PL */
+        } else {
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,0xe0);
+        }
+      } else {
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+      }
 
-  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(HwInfo->jChipType < SIS_315H) {
+      if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300  /* ---- 300 series --- */
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {                  /* 630 - 301B(-DH) */
+        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {                        /* 630 - 301B(-DH) */
 
-          tempah = infoflag >> 8;
-          tempbl = 0;
-           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-             if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-                tempah = SiS_Pr->SiS_LCDInfo;
-                tempbl = (tempah >> 6) & 0x03;
-              }
-           }
-           tempah &= 0xC0;
-           tempah |= 0x20;
-           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-          tempah |= 0xc0;
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-          if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
-             SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
-          }
+           tempah = infoflag >> 8;
+           tempbl = 0;
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+              if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+                 tempah = SiS_Pr->SiS_LCDInfo;
+                 tempbl = (tempah >> 6) & 0x03;
+              }
+           }
+           tempah &= 0xC0;
+           tempah |= 0x20;
+           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+           tempah |= 0xc0;
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+           if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+           }
 
-        } else {                                                       /* 630 - 301 */
+        } else {                                                       /* 630 - 301 */
 
-           tempah = infoflag >> 8;
-           tempah &= 0xC0;
-           tempah |= 0x20;
-          if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+           tempah = ((infoflag >> 8) & 0xc0) | 0x20;
+           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
 
-        }
+        }
 
 #endif /* SIS300 */
 
-     } else {
+      } else {
 
 #ifdef SIS315H  /* ------- 315 series ------ */
 
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {                    /* 315 - LVDS */
+        if(SiS_Pr->SiS_VBType & VB_SISLVDS) {                  /* 315 - LVDS */
 
-          tempbl = 0;
-          if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
-             (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
-             tempah = infoflag >> 8;
-             if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-               tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
-             }
-          } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
-                    (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
-                     tempah = infoflag >> 8;
-             tempbl = 0x03;
-          } else {
-              tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
-             tempbl = (tempah >> 6) & 0x03;
-             tempbl |= 0x08;
-             if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
-          }
-          tempah &= 0xC0;
-           tempah |= 0x20;
-           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-          if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
-           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-          if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-             if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-                SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
-             }
-          }
+           tempbl = 0;
+           if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) &&
+              (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
+              tempah = infoflag >> 8;
+              if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+                tempbl = ((SiS_Pr->SiS_LCDInfo & 0xc0) >> 6);
+              }
+           } else if((SiS_Pr->SiS_CustomT == CUT_CLEVO1400)  &&
+                     (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)) {
+              tempah = infoflag >> 8;
+              tempbl = 0x03;
+           } else {
+              tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x37);
+              tempbl = (tempah >> 6) & 0x03;
+              tempbl |= 0x08;
+              if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempbl |= 0x04;
+           }
+           tempah &= 0xC0;
+           tempah |= 0x20;
+           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)   tempah |= 0xc0;
+           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+           if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+              if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+                 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+              }
+           }
 
-        } else {                                                       /* 315 - TMDS */
+        } else {                                                       /* 315 - TMDS */
 
-           tempah = tempbl = infoflag >> 8;
-          if(!SiS_Pr->UseCustomMode) {
-             tempbl = 0;
-             if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-                if(ModeNo <= 0x13) {
-                   tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
-                }
-             }
-             if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-                if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-                   if(SiS_Pr->SiS_LCDInfo & LCDSync) {
-                      tempah = SiS_Pr->SiS_LCDInfo;
+           tempah = tempbl = infoflag >> 8;
+           if(!SiS_Pr->UseCustomMode) {
+              tempbl = 0;
+              if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+                 if(ModeNo <= 0x13) {
+                    tempah = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
+                 }
+              }
+              if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+                 if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+                   if(SiS_Pr->SiS_LCDInfo & LCDSync) {
+                      tempah = SiS_Pr->SiS_LCDInfo;
                       tempbl = (tempah >> 6) & 0x03;
                    }
-                }
-             }
-          }
-          tempah &= 0xC0;
-           tempah |= 0x20;
-           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
-          if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-             /* Imitate BIOS bug */
-             if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
-          }
-          if((SiS_Pr->SiS_VBType & VB_SIS301C) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-             tempah >>= 3;
-             tempah &= 0x18;
-             SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
-          } else {
-              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
-             if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-                if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-                   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
-                }
-             }
-          }
+                 }
+              }
+           }
+           tempah &= 0xC0;
+           tempah |= 0x20;
+           if(!(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit)) tempah |= 0x10;
+           if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+              /* Imitate BIOS bug */
+              if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)  tempah |= 0xc0;
+           }
+           if((SiS_Pr->SiS_VBType & VB_SIS30xC) && (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
+              tempah >>= 3;
+              tempah &= 0x18;
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,0xe7,tempah);
+           } else {
+              SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x19,0x0F,tempah);
+              if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+                 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+                    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1a,0xf0,tempbl);
+                 }
+              }
+           }
 
-        }
+         }
 #endif  /* SIS315H */
       }
    }
 }
 
-/* Set CRT2 FIFO on 300/630/730 */
+/* Set CRT2 FIFO on 300/540/630/730 */
 #ifdef SIS300
 static void
-SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
-                    PSIS_HW_INFO HwInfo)
-{
-  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
-  USHORT temp,index;
-  USHORT modeidindex,refreshratetableindex;
-  USHORT VCLK=0,MCLK,colorth=0,data2=0;
-  USHORT tempal, tempah, tempbx, tempcl, tempax;
-  USHORT CRT1ModeNo,CRT2ModeNo;
-  USHORT SelectRate_backup;
-  ULONG  data,eax;
-  const UCHAR  LatencyFactor[] = {
-       97, 88, 86, 79, 77, 00,       /*; 64  bit    BQ=2   */
-        00, 87, 85, 78, 76, 54,       /*; 64  bit    BQ=1   */
-        97, 88, 86, 79, 77, 00,       /*; 128 bit    BQ=2   */
-        00, 79, 77, 70, 68, 48,       /*; 128 bit    BQ=1   */
-        80, 72, 69, 63, 61, 00,       /*; 64  bit    BQ=2   */
-        00, 70, 68, 61, 59, 37,       /*; 64  bit    BQ=1   */
-        86, 77, 75, 68, 66, 00,       /*; 128 bit    BQ=2   */
-        00, 68, 66, 59, 57, 37        /*; 128 bit    BQ=1   */
-  };
-  const UCHAR  LatencyFactor730[] = {
-         69, 63, 61,
-        86, 79, 77,
-       103, 96, 94,
-       120,113,111,
-       137,130,128,    /* <-- last entry, data below */
-       137,130,128,    /* to avoid using illegal values */
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-       137,130,128,
-  };
-  const UCHAR ThLowB[]   = {
-       81, 4, 72, 6, 88, 8,120,12,
-        55, 4, 54, 6, 66, 8, 90,12,
-        42, 4, 45, 6, 55, 8, 75,12
-  };
-  const UCHAR ThTiming[] = {
-       1, 2, 2, 3, 0, 1, 1, 2
+SiS_SetCRT2FIFO_300(struct SiS_Private *SiS_Pr,unsigned short ModeNo)
+{
+  unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
+  unsigned short temp, index, modeidindex, refreshratetableindex;
+  unsigned short VCLK = 0, MCLK, colorth = 0, data2 = 0;
+  unsigned short tempbx, tempcl, CRT1ModeNo, CRT2ModeNo, SelectRate_backup;
+  unsigned int   data, pci50, pciA0;
+  static const unsigned char colortharray[] = {
+       1, 1, 2, 2, 3, 4
   };
 
   SelectRate_backup = SiS_Pr->SiS_SelectCRT2Rate;
@@ -5044,232 +5106,159 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
      SiS_SearchModeID(SiS_Pr, &CRT1ModeNo, &modeidindex);
      SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
      SiS_Pr->SiS_SelectCRT2Rate = 0;
-     refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex, HwInfo);
+     refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT1ModeNo, modeidindex);
 
      if(CRT1ModeNo >= 0x13) {
-        index = SiS_Pr->SiS_RefIndex[refreshratetableindex].Ext_CRTVCLK;
-        index &= 0x3F;
-        VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                      /* Get VCLK */
+        /* Get VCLK */
+       index = SiS_GetRefCRTVCLK(SiS_Pr, refreshratetableindex, SiS_Pr->SiS_UseWide);
+       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
 
-       colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex);     /* Get colordepth */
-        colorth >>= 1;
-        if(!colorth) colorth++;
+       /* Get colordepth */
+       colorth = SiS_GetColorDepth(SiS_Pr,CRT1ModeNo,modeidindex) >> 1;
+       if(!colorth) colorth++;
      }
 
   } else {
 
      CRT1ModeNo = 0xfe;
-     VCLK = SiS_Pr->CSRClock_CRT1;                                     /* Get VCLK */
-     data2 = (SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2;
-     switch(data2) {                                                   /* Get color depth */
-        case 0 : colorth = 1; break;
-        case 1 : colorth = 1; break;
-        case 2 : colorth = 2; break;
-        case 3 : colorth = 2; break;
-        case 4 : colorth = 3; break;
-        case 5 : colorth = 4; break;
-        default: colorth = 2;
-     }
+
+     /* Get VCLK */
+     VCLK = SiS_Pr->CSRClock_CRT1;
+
+     /* Get color depth */
+     colorth = colortharray[((SiS_Pr->CModeFlag_CRT1 & ModeTypeMask) - 2)];
 
   }
 
   if(CRT1ModeNo >= 0x13) {
-    if(HwInfo->jChipType == SIS_300) {
-       index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
-    } else {
-       index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
-    }
-    index &= 0x07;
-    MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;                                /* Get MCLK */
+     /* Get MCLK */
+     if(SiS_Pr->ChipType == SIS_300) {
+        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x3A);
+     } else {
+        index = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1A);
+     }
+     index &= 0x07;
+     MCLK = SiS_Pr->SiS_MCLKData_0[index].CLOCK;
 
-    data2 = (colorth * VCLK) / MCLK;
+     temp = ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) >> 6) & 0x03) << 1;
+     if(!temp) temp++;
+     temp <<= 2;
 
-    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-    temp = ((temp & 0x00FF) >> 6) << 1;
-    if(temp == 0) temp = 1;
-    temp <<= 2;
-    temp &= 0xff;
+     data2 = temp - ((colorth * VCLK) / MCLK);
 
-    data2 = temp - data2;
+     temp = (28 * 16) % data2;
+     data2 = (28 * 16) / data2;
+     if(temp) data2++;
 
-    if((28 * 16) % data2) {
-       data2 = (28 * 16) / data2;
-       data2++;
-    } else {
-       data2 = (28 * 16) / data2;
-    }
+     if(SiS_Pr->ChipType == SIS_300) {
 
-    if(HwInfo->jChipType == SIS_300) {
-
-       tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x18);
-       tempah &= 0x62;
-       tempah >>= 1;
-       tempal = tempah;
-       tempah >>= 3;
-       tempal |= tempah;
-       tempal &= 0x07;
-       tempcl = ThTiming[tempal];
-       tempbx = SiS_GetReg(SiS_Pr->SiS_P3c4,0x16);
-       tempbx >>= 6;
-       tempah = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-       tempah >>= 4;
-       tempah &= 0x0c;
-       tempbx |= tempah;
-       tempbx <<= 1;
-       tempal = ThLowB[tempbx + 1];
-       tempal *= tempcl;
-       tempal += ThLowB[tempbx];
-       data = tempal;
-
-    } else if(HwInfo->jChipType == SIS_730) {
-
-#ifdef LINUX_KERNEL
-       SiS_SetRegLong(0xcf8,0x80000050);
-       eax = SiS_GetRegLong(0xcfc);
+       SiS_GetFIFOThresholdIndex300(SiS_Pr, &tempbx, &tempcl);
+       data = SiS_GetFIFOThresholdB300(tempbx, tempcl);
+
+     } else {
+
+#ifdef SIS_LINUX_KERNEL
+       pci50 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0x50);
+       pciA0 = sisfb_read_nbridge_pci_dword(SiS_Pr, 0xa0);
 #else
-       eax = pciReadLong(0x00000000, 0x50);
+       pci50 = pciReadLong(0x00000000, 0x50);
+       pciA0 = pciReadLong(0x00000000, 0xA0);
 #endif
-       tempal = (USHORT)(eax >> 8);
-       tempal &= 0x06;
-       tempal <<= 5;
 
-#ifdef LINUX_KERNEL
-       SiS_SetRegLong(0xcf8,0x800000A0);
-       eax = SiS_GetRegLong(0xcfc);
-#else
-       eax = pciReadLong(0x00000000, 0xA0);
-#endif
-       temp = (USHORT)(eax >> 28);
-       temp &= 0x0F;
-       tempal |= temp;
-
-       tempbx = tempal;   /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
-       tempbx = 0;        /* -- do it like the BIOS anyway... */
-       tempax = tempbx;
-       tempbx &= 0xc0;
-       tempbx >>= 6;
-       tempax &= 0x0f;
-       tempax *= 3;
-       tempbx += tempax;
-
-       data = LatencyFactor730[tempbx];
-       data += 15;
-       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-       if(!(temp & 0x80)) data += 5;
+        if(SiS_Pr->ChipType == SIS_730) {
 
-    } else {
+          index = (unsigned short)(((pciA0 >> 28) & 0x0f) * 3);
+          index += (unsigned short)(((pci50 >> 9)) & 0x03);
 
-       index = 0;
-       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-       if(temp & 0x0080) index += 12;
+          /* BIOS BUG (2.04.5d, 2.04.6a use ah here, which is unset!) */
+          index = 0;  /* -- do it like the BIOS anyway... */
 
-#ifdef LINUX_KERNEL
-       SiS_SetRegLong(0xcf8,0x800000A0);
-       eax = SiS_GetRegLong(0xcfc);
-#else
-       /* We use pci functions X offers. We use tag 0, because
-        * we want to read/write to the host bridge (which is always
-        * 00:00.0 on 630, 730 and 540), not the VGA device.
-        */
-       eax = pciReadLong(0x00000000, 0xA0);
-#endif
-       temp = (USHORT)(eax >> 24);
-       if(!(temp&0x01)) index += 24;
-
-#ifdef LINUX_KERNEL
-       SiS_SetRegLong(0xcf8,0x80000050);
-       eax = SiS_GetRegLong(0xcfc);
-#else
-       eax = pciReadLong(0x00000000, 0x50);
-#endif
-       temp=(USHORT)(eax >> 24);
-       if(temp & 0x01) index += 6;
+       } else {
 
-       temp = (temp & 0x0F) >> 1;
-       index += temp;
+          pci50 >>= 24;
+          pciA0 >>= 24;
 
-       data = LatencyFactor[index];
-       data += 15;
-       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-       if(!(temp & 0x80)) data += 5;
-    }
+          index = (pci50 >> 1) & 0x07;
+
+          if(pci50 & 0x01)    index += 6;
+          if(!(pciA0 & 0x01)) index += 24;
+
+          if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80) index += 12;
 
-    data += data2;                             /* CRT1 Request Period */
+       }
 
-    SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-    SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+       data = SiS_GetLatencyFactor630(SiS_Pr, index) + 15;
+       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x80)) data += 5;
 
-    if(!SiS_Pr->UseCustomMode) {
+     }
 
-       CRT2ModeNo = ModeNo;
-       SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
+     data += data2;                                            /* CRT1 Request Period */
 
-       refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex, HwInfo);
+     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
 
-       index = SiS_GetVCLK2Ptr(SiS_Pr,CRT2ModeNo,modeidindex,
-                               refreshratetableindex,HwInfo);
-       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;                /* Get VCLK  */
+     if(!SiS_Pr->UseCustomMode) {
 
-       if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-          if(SiS_Pr->SiS_UseROM) {
-            if(ROMAddr[0x220] & 0x01) {
-                VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
-            }
-          }
-       }
+       CRT2ModeNo = ModeNo;
+       SiS_SearchModeID(SiS_Pr, &CRT2ModeNo, &modeidindex);
 
-    } else {
+       refreshratetableindex = SiS_GetRatePtr(SiS_Pr, CRT2ModeNo, modeidindex);
 
-       CRT2ModeNo = 0xfe;
-       VCLK = SiS_Pr->CSRClock;                                        /* Get VCLK */
+       /* Get VCLK  */
+       index = SiS_GetVCLK2Ptr(SiS_Pr, CRT2ModeNo, modeidindex, refreshratetableindex);
+       VCLK = SiS_Pr->SiS_VCLKData[index].CLOCK;
 
-    }
+       if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
+          if(SiS_Pr->SiS_UseROM) {
+             if(ROMAddr[0x220] & 0x01) {
+                VCLK = ROMAddr[0x229] | (ROMAddr[0x22a] << 8);
+             }
+           }
+        }
+
+     } else {
+
+       /* Get VCLK */
+       CRT2ModeNo = 0xfe;
+       VCLK = SiS_Pr->CSRClock;
+
+     }
 
-    colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex); /* Get colordepth */
-    colorth >>= 1;
-    if(!colorth) colorth++;
+     /* Get colordepth */
+     colorth = SiS_GetColorDepth(SiS_Pr,CRT2ModeNo,modeidindex) >> 1;
+     if(!colorth) colorth++;
 
-    data = data * VCLK * colorth;
-    if(data % (MCLK << 4)) {
-       data = data / (MCLK << 4);
-       data++;
-    } else {
-       data = data / (MCLK << 4);
-    }
+     data = data * VCLK * colorth;
+     temp = data % (MCLK << 4);
+     data = data / (MCLK << 4);
+     if(temp) data++;
 
-    if(data <= 6) data = 6;
-    if(data > 0x14) data = 0x14;
+     if(data < 6) data = 6;
+     else if(data > 0x14) data = 0x14;
 
-    temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x01);
-    if(HwInfo->jChipType == SIS_300) {
-       if(data <= 0x0f) temp = (temp & (~0x1F)) | 0x13;
-       else             temp = (temp & (~0x1F)) | 0x16;
-       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
-                 temp = (temp & (~0x1F)) | 0x13;
-       }
-    } else {
-       if( ( (HwInfo->jChipType == SIS_630) ||
-             (HwInfo->jChipType == SIS_730) )  &&
-           (HwInfo->jChipRevision >= 0x30) ) /* 630s or 730(s?) */
-      {
-         temp = (temp & (~0x1F)) | 0x1b;
-      } else {
-         temp = (temp & (~0x1F)) | 0x16;
-      }
-    }
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
+     if(SiS_Pr->ChipType == SIS_300) {
+        temp = 0x16;
+       if((data <= 0x0f) || (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024))
+          temp = 0x13;
+     } else {
+        temp = 0x16;
+       if(( (SiS_Pr->ChipType == SIS_630) ||
+            (SiS_Pr->ChipType == SIS_730) )  &&
+          (SiS_Pr->ChipRevision >= 0x30))
+          temp = 0x1b;
+     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0xe0,temp);
 
-    if( (HwInfo->jChipType == SIS_630) &&
-        (HwInfo->jChipRevision >= 0x30) ) /* 630s, NOT 730 */
-    {
-       if(data > 0x13) data = 0x13;
-    }
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
+     if((SiS_Pr->ChipType == SIS_630) &&
+       (SiS_Pr->ChipRevision >= 0x30)) {
+       if(data > 0x13) data = 0x13;
+     }
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,0xe0,data);
 
   } else {  /* If mode <= 0x13, we just restore everything */
 
-    SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
-    SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
+     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+     SiS_Pr->SiS_SelectCRT2Rate = SelectRate_backup;
 
   }
 }
@@ -5278,10 +5267,10 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,USHORT ModeNo,
 /* Set CRT2 FIFO on 315/330 series */
 #ifdef SIS315H
 static void
-SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2FIFO_310(struct SiS_Private *SiS_Pr)
 {
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  if( (HwInfo->jChipType == SIS_760)      &&
+  if( (SiS_Pr->ChipType == SIS_760)      &&
       (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
       (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
       (SiS_Pr->SiS_VGAHDE >= 1280)       &&
@@ -5299,337 +5288,162 @@ SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 }
 #endif
 
-static USHORT
-SiS_GetVGAHT2(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_GetVGAHT2(struct SiS_Private *SiS_Pr)
 {
-  ULONG tempax,tempbx;
+  unsigned int tempax,tempbx;
 
   tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
   tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
   tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
-  return((USHORT)tempax);
+  return (unsigned short)tempax;
 }
 
 /* Set Part 1 / SiS bridge slave mode */
 static void
-SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
-                  PSIS_HW_INFO HwInfo,USHORT RefreshRateTableIndex)
-{
-  USHORT  push1,push2;
-  USHORT  tempax,tempbx,tempcx,temp;
-  USHORT  resinfo,modeflag,xres=0;
-  unsigned char p1_7, p1_8;
+SiS_SetGroup1_301(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+                  unsigned short RefreshRateTableIndex)
+{
+  unsigned short temp, modeflag, i, j, xres=0, VGAVDE;
+  static const unsigned short CRTranslation[] = {
+       /* CR0   CR1   CR2   CR3   CR4   CR5   CR6   CR7   */
+         0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+       /* CR8   CR9   SR0A  SR0B  SR0C  SR0D  SR0E  CR0F  */
+         0x00, 0x0b, 0x17, 0x18, 0x19, 0x00, 0x1a, 0x00,
+       /* CR10  CR11  CR12  CR13  CR14  CR15  CR16  CR17  */
+         0x0c, 0x0d, 0x0e, 0x00, 0x0f, 0x10, 0x11, 0x00
+  };
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-     resinfo = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ResInfo;
   } else if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
-     resinfo = 0;
      xres = SiS_Pr->CHDisplay;
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-     resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      xres = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].XRes;
   }
 
   /* The following is only done if bridge is in slave mode: */
 
-  if((HwInfo->jChipType >= SIS_661) && (ModeNo > 0x13)) {
-     if(xres >= 1600) {
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(xres >= 1600) {  /* BIOS: == 1600 */
         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x31,0x04);
      }
   }
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x03,0xff);                  /* set MAX HT */
+  SiS_Pr->CHTotal = 8224;  /* Max HT, 0x2020, results in 0x3ff in registers */
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)  modeflag |= Charx8Dot;
-
-  if(modeflag & Charx8Dot) tempcx = 0x08;
-  else                     tempcx = 0x09;
-
-  tempax = SiS_Pr->SiS_VGAHDE;                                         /* 0x04 Horizontal Display End */
-  if(modeflag & HalfDCLK) tempax >>= 1;
-  tempax = ((tempax / tempcx) - 1) & 0xff;
-  tempbx = tempax;
-
-  temp = tempax;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x04,temp);
+  SiS_Pr->CHDisplay = SiS_Pr->SiS_VGAHDE;
+  if(modeflag & HalfDCLK) SiS_Pr->CHDisplay >>= 1;
 
+  SiS_Pr->CHBlankStart = SiS_Pr->CHDisplay;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) {
-        temp += 2;
-     }
-  }
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     if(resinfo == SIS_RI_800x600) temp -= 2;
-  }
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x05,temp);                 /* 0x05 Horizontal Display Start */
-
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x06,0x03);                 /* 0x06 Horizontal Blank end     */
-
-  tempax = 0xFFFF;
-  if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempax = SiS_GetVGAHT2(SiS_Pr);
-  if(tempax >= SiS_Pr->SiS_VGAHT) tempax = SiS_Pr->SiS_VGAHT;
-  if(modeflag & HalfDCLK)         tempax >>= 1;
-  tempax = (tempax / tempcx) - 5;
-  tempcx = tempax;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     temp = tempcx - 1;
-     if(!(modeflag & HalfDCLK)) {
-        temp -= 6;
-        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-           temp -= 2;
-           if(ModeNo > 0x13) temp -= 10;
-        }
-     }
-  } else {
-     tempcx = (tempcx + tempbx) >> 1;
-     temp = (tempcx & 0x00FF) + 2;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        temp--;
-        if(!(modeflag & HalfDCLK)) {
-           if((modeflag & Charx8Dot)) {
-              temp += 4;
-              if(SiS_Pr->SiS_VGAHDE >= 800) temp -= 6;
-              if(HwInfo->jChipType >= SIS_315H) {
-                if(SiS_Pr->SiS_VGAHDE == 800) temp += 2;
-              }
-           }
-        }
-     } else {
-        if(!(modeflag & HalfDCLK)) {
-           temp -= 4;
-           if((SiS_Pr->SiS_LCDResInfo != Panel_1280x960) &&
-             (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)) {
-              if(SiS_Pr->SiS_VGAHDE >= 800) {
-                 temp -= 7;
-                if(HwInfo->jChipType < SIS_315H) {
-                    if(SiS_Pr->SiS_ModeType == ModeEGA) {
-                       if(SiS_Pr->SiS_VGAVDE == 1024) {
-                          temp += 15;
-                          if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
-                            temp += 7;
-                       }
-                    }
-                }
-                if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
-                    if(SiS_Pr->SiS_VGAHDE >= 1280) {
-                       if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) temp += 28;
-                   }
-                 }
-              }
-           }
-        }
-     }
+     SiS_Pr->CHBlankStart += 16;
   }
 
-  p1_7 = temp;
-  p1_8 = 0x00;
-
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-        if(ModeNo <= 0x01) {
-          p1_7 = 0x2a;
-          if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_8 = 0x61;
-          else                                 p1_8 = 0x41;
-       } else if(SiS_Pr->SiS_ModeType == ModeText) {
-          if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) p1_7 = 0x54;
-          else                                 p1_7 = 0x55;
-          p1_8 = 0x00;
-       } else if(ModeNo <= 0x13) {
-          if(modeflag & HalfDCLK) {
-             if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-                p1_7 = 0x30;
-                p1_8 = 0x03;
-             } else {
-                p1_7 = 0x2f;
-                p1_8 = 0x02;
-             }
-          } else {
-             p1_7 = 0x5b;
-             p1_8 = 0x03;
-          }
-       } else if( ((HwInfo->jChipType >= SIS_315H) &&
-                   ((ModeNo == 0x50) || (ModeNo == 0x56) || (ModeNo == 0x53))) ||
-                  ((HwInfo->jChipType < SIS_315H) &&
-                   (resinfo == SIS_RI_320x200 || resinfo == SIS_RI_320x240)) ) {
-          if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-             p1_7 = 0x30,
-             p1_8 = 0x03;
-          } else {
-             p1_7 = 0x2f;
-             p1_8 = 0x03;
-          }
-        }
-     }
+  SiS_Pr->CHBlankEnd = 32;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(xres == 1600) SiS_Pr->CHBlankEnd += 80;
   }
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-     if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p)) {
-        p1_7 = 0x63;
-       if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) p1_7 = 0x55;
-     }
-     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-        if(!(modeflag & HalfDCLK)) {
-          p1_7 = 0xb2;
-          if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
-             p1_7 = 0xab;
-          }
-       }
-     } else {
-        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
-          if(modeflag & HalfDCLK) p1_7 = 0x30;
-       }
-     }
+  temp = SiS_Pr->SiS_VGAHT - 96;
+  if(!(modeflag & HalfDCLK)) temp -= 32;
+  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x04);
+     temp |= ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x0b) & 0xc0) << 2);
+     temp -= 3;
+     temp <<= 3;
+  } else {
+     if(SiS_Pr->SiS_RVBHRS2) temp = SiS_Pr->SiS_RVBHRS2;
   }
+  SiS_Pr->CHSyncStart = temp;
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x07,p1_7);                 /* 0x07 Horizontal Retrace Start */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,p1_8);                 /* 0x08 Horizontal Retrace End   */
-
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,0x03);                 /* 0x18 SR08 (FIFO Threshold?)   */
+  SiS_Pr->CHSyncEnd = 0xffe8;  /* results in 0x2000 in registers */
 
-  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x19,0xF0);
+  SiS_Pr->CVTotal = 2049;      /* Max VT, 0x0801, results in 0x7ff in registers */
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x09,0xFF);                 /* 0x09 Set Max VT    */
+  VGAVDE = SiS_Pr->SiS_VGAVDE;
+  if     (VGAVDE ==  357) VGAVDE =  350;
+  else if(VGAVDE ==  360) VGAVDE =  350;
+  else if(VGAVDE ==  375) VGAVDE =  350;
+  else if(VGAVDE ==  405) VGAVDE =  400;
+  else if(VGAVDE ==  420) VGAVDE =  400;
+  else if(VGAVDE ==  525) VGAVDE =  480;
+  else if(VGAVDE == 1056) VGAVDE = 1024;
+  SiS_Pr->CVDisplay = VGAVDE;
 
-  tempcx = 0x121;
-  tempbx = SiS_Pr->SiS_VGAVDE;                                 /* 0x0E Vertical Display End */
-  if     (tempbx == 357) tempbx = 350;
-  else if(tempbx == 360) tempbx = 350;
-  else if(tempbx == 375) tempbx = 350;
-  else if(tempbx == 405) tempbx = 400;
-  else if(tempbx == 420) tempbx = 400;
-  else if(tempbx == 525) tempbx = 480;
-  push2 = tempbx;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-       if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
-           if     (tempbx == 350) tempbx += 5;
-           else if(tempbx == 480) tempbx += 5;
-       }
-     }
-  }
-  tempbx -= 2;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);                 /* 0x10 vertical Blank Start */
-
-  tempbx = push2;
-  tempbx--;
-  temp = tempbx & 0x00FF;
-#if 0
-  /* Missing code from 630/301B 2.04.5a and 650/302LV 1.10.6s (calles int 2f) */
-  if(xxx()) {
-      if(temp == 0xdf) temp = 0xda;
-  }
-#endif
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);
-
-  temp = 0;
-  if(modeflag & DoubleScanMode) temp |= 0x80;
-  if(HwInfo->jChipType >= SIS_661) {
-     if(tempbx & 0x0200)        temp |= 0x20;
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x0B,0x5F,temp);
-     if(tempbx & 0x0100)  tempcx |= 0x000a;
-     if(tempbx & 0x0400)  tempcx |= 0x1200;
-  } else {
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);
-     if(tempbx & 0x0100)  tempcx |= 0x0002;
-     if(tempbx & 0x0400)  tempcx |= 0x0600;
-  }
+  SiS_Pr->CVBlankStart = SiS_Pr->CVDisplay;
 
-  if(tempbx & 0x0200)  tempcx |= 0x0040;
+  SiS_Pr->CVBlankEnd = 1;
+  if(ModeNo == 0x3c) SiS_Pr->CVBlankEnd = 226;
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,0x00);                 /* 0x11 Vertical Blank End */
+  temp = (SiS_Pr->SiS_VGAVT - VGAVDE) >> 1;
+  SiS_Pr->CVSyncStart = VGAVDE + temp;
 
-  tempax = (SiS_Pr->SiS_VGAVT - tempbx) >> 2;
+  temp >>= 3;
+  SiS_Pr->CVSyncEnd = SiS_Pr->CVSyncStart + temp;
 
-  if((ModeNo > 0x13) || (HwInfo->jChipType < SIS_315H)) {
-     if(resinfo != SIS_RI_1280x1024) {
-       tempbx += (tempax << 1);
-     }
-  } else if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_LCDResInfo != Panel_1400x1050) {
-       tempbx += (tempax << 1);
-     }
-  }
+  SiS_CalcCRRegisters(SiS_Pr, 0);
+  SiS_Pr->CCRT1CRTC[16] &= ~0xE0;
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-     tempbx -= 10;
-  } else {
-     if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-        if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-           tempbx += 40;
-          if(HwInfo->jChipType >= SIS_315H) {
-             if(SiS_Pr->SiS_VGAHDE == 800) tempbx += 10;
-          }
-       }
-     }
+  for(i = 0; i <= 7; i++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[i]);
   }
-  tempax >>= 2;
-  tempax++;
-  tempax += tempbx;
-  push1 = tempax;
-  if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-     if(tempbx <= 513)  {
-       if(tempax >= 513) tempbx = 513;
-     }
+  for(i = 0x10, j = 8; i <= 0x12; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
   }
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);                 /* 0x0C Vertical Retrace Start */
-
-  tempbx--;
-  temp = tempbx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,temp);
-
-  if(tempbx & 0x0100) tempcx |= 0x0008;
-
-  if(tempbx & 0x0200) {
-     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x0B,0x20);
+  for(i = 0x15, j = 11; i <= 0x16; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
   }
-  tempbx++;
-
-  if(tempbx & 0x0100) tempcx |= 0x0004;
-  if(tempbx & 0x0200) tempcx |= 0x0080;
-  if(tempbx & 0x0400) {
-     if(HwInfo->jChipType >= SIS_661)        tempcx |= 0x0800;
-     else if(SiS_Pr->SiS_VBType & VB_SIS301) tempcx |= 0x0800;
-     else                                    tempcx |= 0x0C00;
+  for(i = 0x0a, j = 13; i <= 0x0c; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,CRTranslation[i],SiS_Pr->CCRT1CRTC[j]);
   }
 
-  tempbx = push1;
-  temp = tempbx & 0x000F;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                 /* 0x0D vertical Retrace End */
-
-  if(tempbx & 0x0010) tempcx |= 0x2000;
-
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);                 /* 0x0A CR07 */
+  temp = SiS_Pr->CCRT1CRTC[16] & 0xE0;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x0E],0x1F,temp);
 
-  temp = (tempcx & 0xFF00) >> 8;
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x17,temp);                 /* 0x17 SR0A */
-
-  tempax = modeflag;
-  temp = (tempax & 0xFF00) >> 8;
-  temp = (temp >> 1) & 0x09;
-  if(!(SiS_Pr->SiS_VBType & VB_SIS301)) temp |= 0x01;          /* Always 8 dotclock */
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                 /* 0x16 SR01 */
+  temp = (SiS_Pr->CCRT1CRTC[16] & 0x01) << 5;
+  if(modeflag & DoubleScanMode) temp |= 0x80;
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,CRTranslation[0x09],0x5F,temp);
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);                 /* 0x0F CR14 */
+  temp = 0;
+  temp |= (SiS_GetReg(SiS_Pr->SiS_P3c4,0x01) & 0x01);
+  if(modeflag & HalfDCLK) temp |= 0x08;
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x16,temp);                 /* SR01: HalfDCLK[3], 8/9 div dotclock[0] */
 
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);                 /* 0x12 CR17 */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,0x00);                 /* CR14: (text mode: underline location) */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,0x00);                 /* CR17: n/a */
 
-  temp = 0x00;
+  temp = 0;
   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
-     if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
-       temp = 0x80;
-     }
+     temp = (SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) << 7;
   }
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                 /* 0x1A SR0E */
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1A,temp);                 /* SR0E, dither[7] */
 
   temp = SiS_GetRegByte((SiS_Pr->SiS_P3ca+0x02));
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1b,temp);                 /* ? */
+
+#ifdef SIS_XORG_XF86
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "%d %d %d %d  %d %d %d %d  (%d %d %d %d)\n",
+       SiS_Pr->CHDisplay, SiS_Pr->CHSyncStart, SiS_Pr->CHSyncEnd, SiS_Pr->CHTotal,
+       SiS_Pr->CVDisplay, SiS_Pr->CVSyncStart, SiS_Pr->CVSyncEnd, SiS_Pr->CVTotal,
+       SiS_Pr->CHBlankStart, SiS_Pr->CHBlankEnd, SiS_Pr->CVBlankStart, SiS_Pr->CVBlankEnd);
+
+   xf86DrvMsg(0, X_INFO, " {{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+       SiS_Pr->CCRT1CRTC[0], SiS_Pr->CCRT1CRTC[1],
+       SiS_Pr->CCRT1CRTC[2], SiS_Pr->CCRT1CRTC[3],
+       SiS_Pr->CCRT1CRTC[4], SiS_Pr->CCRT1CRTC[5],
+       SiS_Pr->CCRT1CRTC[6], SiS_Pr->CCRT1CRTC[7]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,\n",
+       SiS_Pr->CCRT1CRTC[8], SiS_Pr->CCRT1CRTC[9],
+       SiS_Pr->CCRT1CRTC[10], SiS_Pr->CCRT1CRTC[11],
+       SiS_Pr->CCRT1CRTC[12], SiS_Pr->CCRT1CRTC[13],
+       SiS_Pr->CCRT1CRTC[14], SiS_Pr->CCRT1CRTC[15]);
+   xf86DrvMsg(0, X_INFO, "   0x%02x}},\n", SiS_Pr->CCRT1CRTC[16]);
+#endif
+#endif
 }
 
 /* Setup panel link
@@ -5637,18 +5451,18 @@ SiS_SetGroup1_301(SiS_Private *SiS_Pr, USHORT ModeNo,USHORT ModeIdIndex,
  * 300/LVDS+TV, 300/301B-DH, 315/LVDS+TV, 315/LCDA
  */
 static void
-SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
 {
-  USHORT modeflag,resinfo;
-  USHORT push2,tempax,tempbx,tempcx,temp;
-  ULONG tempeax=0,tempebx,tempecx,tempvcfact=0;
+  unsigned short modeflag, resinfo = 0;
+  unsigned short push2, tempax, tempbx, tempcx, temp;
+  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
   BOOLEAN islvds = FALSE, issis  = FALSE, chkdclkfirst = FALSE;
 #ifdef SIS300
-  USHORT crt2crtc;
+  unsigned short crt2crtc = 0;
 #endif
 #ifdef SIS315H
-  USHORT pushcx;
+  unsigned short pushcx;
 #endif
 
   if(ModeNo <= 0x13) {
@@ -5659,15 +5473,11 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 #endif
   } else if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
-     resinfo = 0;
-#ifdef SIS300
-     crt2crtc = 0;
-#endif
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
 #ifdef SIS300
-     crt2crtc = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+     crt2crtc = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 #endif
   }
 
@@ -5681,14 +5491,14 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      issis = TRUE;
   }
 
-  if((HwInfo->jChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
+  if((SiS_Pr->ChipType >= SIS_315H) && (islvds) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA))) {
      if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
         chkdclkfirst = TRUE;
      }
   }
 
 #ifdef SIS315H
-  if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+  if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
      if(IS_SIS330) {
         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x10);
      } else if(IS_SIS740) {
@@ -5704,7 +5514,7 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
           SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x00);
         } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2D,0x0f);
-          if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+          if(SiS_Pr->SiS_VBType & VB_SIS30xC) {
              if((SiS_Pr->SiS_LCDResInfo == Panel_1024x768) ||
                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2D,0x20);
@@ -5720,10 +5530,10 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   tempax = SiS_Pr->SiS_LCDHDES;
   if(islvds) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if((!SiS_Pr->SiS_IF_DEF_FSTN) && (!SiS_Pr->SiS_IF_DEF_DSTN)) {
-           if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
-              (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
-             tempax -= 8;
+       if(!SiS_Pr->SiS_IF_DEF_FSTN && !SiS_Pr->SiS_IF_DEF_DSTN) {
+          if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) &&
+             (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))) {
+             tempax -= 8;
           }
        }
      }
@@ -5736,13 +5546,14 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   tempbx = SiS_Pr->SiS_HDE;
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-     if((SiS_Pr->SiS_LCDResInfo == Panel_640x480_2) ||
-        (SiS_Pr->SiS_LCDResInfo == Panel_640x480_3)) {
-        tempbx >>= 1;
-     }
      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
         tempbx = SiS_Pr->PanelXRes;
      }
+     if((SiS_Pr->SiS_LCDResInfo == Panel_320x240_1) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_2) ||
+        (SiS_Pr->SiS_LCDResInfo == Panel_320x240_3)) {
+        tempbx >>= 1;
+     }
   }
 
   tempax += tempbx;
@@ -5767,25 +5578,25 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   temp = (tempcx >> 3) & 0x00FF;
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
      if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-        if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-           switch(ModeNo) {
-           case 0x04:
-           case 0x05:
-           case 0x0d: temp = 0x56; break;
-           case 0x10: temp = 0x60; break;
-           case 0x13: temp = 0x5f; break;
-           case 0x40:
-           case 0x41:
-           case 0x4f:
-           case 0x43:
-           case 0x44:
-           case 0x62:
-           case 0x56:
-           case 0x53:
-           case 0x5d:
-           case 0x5e: temp = 0x54; break;
-           }
-        }
+       if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
+          switch(ModeNo) {
+          case 0x04:
+          case 0x05:
+          case 0x0d: temp = 0x56; break;
+          case 0x10: temp = 0x60; break;
+          case 0x13: temp = 0x5f; break;
+          case 0x40:
+          case 0x41:
+          case 0x4f:
+          case 0x43:
+          case 0x44:
+          case 0x62:
+          case 0x56:
+          case 0x53:
+          case 0x5d:
+          case 0x5e: temp = 0x54; break;
+          }
+       }
      }
   }
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x14,temp);                 /* BPLHRS */
@@ -5793,12 +5604,12 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
      temp += 2;
      if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-        temp += 8;
-        if(SiS_Pr->PanelHRE != 999) {
-           temp = tempcx + SiS_Pr->PanelHRE;
+       temp += 8;
+       if(SiS_Pr->PanelHRE != 999) {
+          temp = tempcx + SiS_Pr->PanelHRE;
           if(temp >= SiS_Pr->SiS_HT) temp -= SiS_Pr->SiS_HT;
           temp >>= 3;
-        }
+       }
      }
   } else {
      temp += 10;
@@ -5806,9 +5617,6 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   temp &= 0x1F;
   temp |= ((tempcx & 0x07) << 5);
-#if 0
-  if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0x20;                     /* WRONG? BIOS loads cl, not ah */
-#endif
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x15,temp);                 /* BPLHRE */
 
   /* Vertical */
@@ -5826,9 +5634,9 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   push2 = tempbx;
 
   tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE;
-  if(HwInfo->jChipType < SIS_315H) {
+  if(SiS_Pr->ChipType < SIS_315H) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
+       if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
           tempcx = SiS_Pr->SiS_VGAVT - SiS_Pr->PanelYRes;
        }
      }
@@ -5844,19 +5652,19 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      if(issis) tempbx++;
   } else {
      tempbx += tempcx;
-     if(HwInfo->jChipType < SIS_315H) tempbx++;
+     if(SiS_Pr->ChipType < SIS_315H) tempbx++;
      else if(issis)                   tempbx++;
   }
 
-  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;       /* BPLVRS  */
+  if(tempbx >= SiS_Pr->SiS_VT) tempbx -= SiS_Pr->SiS_VT;
 
   temp = tempbx & 0x00FF;
   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-        if(ModeNo == 0x10) temp = 0xa9;
+       if(ModeNo == 0x10) temp = 0xa9;
      }
   }
-  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x18,temp);                 /* BPLVRS */
 
   tempcx >>= 3;
   tempcx++;
@@ -5879,13 +5687,13 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   } else if(SiS_Pr->SiS_VGAVDE != SiS_Pr->SiS_VDE) temp |= 0x40;
   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA)          temp |= 0x40;
   tempbx = 0x87;
-  if((HwInfo->jChipType >= SIS_315H) ||
-     (HwInfo->jChipRevision >= 0x30)) {
+  if((SiS_Pr->ChipType >= SIS_315H) ||
+     (SiS_Pr->ChipRevision >= 0x30)) {
      tempbx = 0x07;
      if((SiS_Pr->SiS_IF_DEF_CH70xx == 1) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
        if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x03)    temp |= 0x80;
      }
-     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit mutliplexed) via VGA2 */
+     /* Chrontel 701x operates in 24bit mode (8-8-8, 2x12bit multiplexed) via VGA2 */
      if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
           if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x06) & 0x10)      temp |= 0x80;
@@ -5896,59 +5704,58 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   }
   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x1A,tempbx,temp);
 
-  tempbx = push2;                                                      /* BPLVDEE */
+  tempbx = push2;                                              /* BPLVDEE */
 
-  tempcx = SiS_Pr->SiS_LCDVDES;                                        /* BPLVDES */
+  tempcx = SiS_Pr->SiS_LCDVDES;                                        /* BPLVDES */
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
      switch(SiS_Pr->SiS_LCDResInfo) {
      case Panel_640x480:
-        tempbx = SiS_Pr->SiS_VGAVDE - 1;
-        tempcx = SiS_Pr->SiS_VGAVDE;
+       tempbx = SiS_Pr->SiS_VGAVDE - 1;
+       tempcx = SiS_Pr->SiS_VGAVDE;
        break;
      case Panel_800x600:
-        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-           if(resinfo == SIS_RI_800x600) tempcx++;
-        }
+       if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+          if(resinfo == SIS_RI_800x600) tempcx++;
+       }
        break;
      case Panel_1024x600:
-        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-           if(resinfo == SIS_RI_1024x600) tempcx++;
-           if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
+       if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+          if(resinfo == SIS_RI_1024x600) tempcx++;
+          if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
              if(resinfo == SIS_RI_800x600) tempcx++;
           }
-        }
+       }
        break;
      case Panel_1024x768:
-        if(HwInfo->jChipType < SIS_315H) {
-           if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-              if(resinfo == SIS_RI_1024x768) tempcx++;
+       if(SiS_Pr->ChipType < SIS_315H) {
+          if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+             if(resinfo == SIS_RI_1024x768) tempcx++;
           }
-        }
+       }
        break;
      }
   }
 
   temp = ((tempbx >> 8) & 0x07) << 3;
-  temp = temp | ((tempcx >> 8) & 0x07);
+  temp |= ((tempcx >> 8) & 0x07);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1D,temp);
-  /* if(SiS_Pr->SiS_IF_DEF_FSTN) tempbx++;  */
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1C,tempbx);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1B,tempcx);
 
   /* Vertical scaling */
 
-  if(HwInfo->jChipType < SIS_315H) {
+  if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300      /* 300 series */
      tempeax = SiS_Pr->SiS_VGAVDE << 6;
-     temp = (tempeax % (ULONG)SiS_Pr->SiS_VDE);
-     tempeax = tempeax / (ULONG)SiS_Pr->SiS_VDE;
+     temp = (tempeax % (unsigned int)SiS_Pr->SiS_VDE);
+     tempeax = tempeax / (unsigned int)SiS_Pr->SiS_VDE;
      if(temp) tempeax++;
 
      if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) tempeax = 0x3F;
 
-     temp = (USHORT)(tempeax & 0x00FF);
+     temp = (unsigned short)(tempeax & 0x00FF);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1E,temp);              /* BPLVCFACT */
      tempvcfact = temp;
 #endif /* SIS300 */
@@ -5963,20 +5770,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      if(temp) tempeax++;
      tempvcfact = tempeax;
 
-     temp = (USHORT)(tempeax & 0x00FF);
+     temp = (unsigned short)(tempeax & 0x00FF);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x37,temp);
-     temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+     temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x36,temp);
-     temp = (USHORT)((tempeax & 0x00030000) >> 16);
+     temp = (unsigned short)((tempeax & 0x00030000) >> 16);
      if(SiS_Pr->SiS_VDE == SiS_Pr->SiS_VGAVDE) temp |= 0x04;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x35,temp);
 
-     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
-        temp = (USHORT)(tempeax & 0x00FF);
+     if(SiS_Pr->SiS_VBType & VB_SISPART4SCALER) {
+        temp = (unsigned short)(tempeax & 0x00FF);
         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3c,temp);
-        temp = (USHORT)((tempeax & 0x00FF00) >> 8);
+        temp = (unsigned short)((tempeax & 0x00FF00) >> 8);
         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x3b,temp);
-        temp = (USHORT)(((tempeax & 0x00030000) >> 16) << 6);
+        temp = (unsigned short)(((tempeax & 0x00030000) >> 16) << 6);
         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0x3f,temp);
         temp = 0;
         if(SiS_Pr->SiS_VDE != SiS_Pr->SiS_VGAVDE) temp |= 0x08;
@@ -5997,29 +5804,29 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      tempecx = 0xFFFF;
   } else {
      tempecx = tempebx / SiS_Pr->SiS_HDE;
-     if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->ChipType >= SIS_315H) {
         if(tempebx % SiS_Pr->SiS_HDE) tempecx++;
      }
   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
+  if(SiS_Pr->ChipType >= SIS_315H) {
      tempeax = (tempebx / tempecx) - 1;
   } else {
      tempeax = ((SiS_Pr->SiS_VGAHT << 16) / tempecx) - 1;
   }
   tempecx = (tempecx << 16) | (tempeax & 0xFFFF);
-  temp = (USHORT)(tempecx & 0x00FF);
+  temp = (unsigned short)(tempecx & 0x00FF);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1F,temp);
 
-  if(HwInfo->jChipType >= SIS_315H) {
+  if(SiS_Pr->ChipType >= SIS_315H) {
      tempeax = (SiS_Pr->SiS_VGAVDE << 18) / tempvcfact;
-     tempbx = (USHORT)(tempeax & 0xFFFF);
+     tempbx = (unsigned short)(tempeax & 0xFFFF);
   } else {
      tempeax = SiS_Pr->SiS_VGAVDE << 6;
      tempbx = tempvcfact & 0x3f;
      if(tempbx == 0) tempbx = 64;
      tempeax /= tempbx;
-     tempbx = (USHORT)(tempeax & 0xFFFF);
+     tempbx = (unsigned short)(tempeax & 0xFFFF);
   }
   if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) tempbx--;
   if(SiS_Pr->SiS_SetFlag & EnableLVDSDDA) {
@@ -6032,24 +5839,24 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x20,temp);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x21,tempbx);
 
-  tempecx >>= 16;                                              /* BPLHCFACT  */
+  tempecx >>= 16;                                              /* BPLHCFACT  */
   if(!chkdclkfirst) {
      if(modeflag & HalfDCLK) tempecx >>= 1;
   }
-  temp = (USHORT)((tempecx & 0xFF00) >> 8);
+  temp = (unsigned short)((tempecx & 0xFF00) >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x22,temp);
-  temp = (USHORT)(tempecx & 0x00FF);
+  temp = (unsigned short)(tempecx & 0x00FF);
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x23,temp);
 
 #ifdef SIS315H
-  if(HwInfo->jChipType >= SIS_315H) {
+  if(SiS_Pr->ChipType >= SIS_315H) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SIS301LV302LV)) {
+        if((islvds) || (SiS_Pr->SiS_VBInfo & VB_SISLVDS)) {
            SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x20);
        }
      } else {
         if(islvds) {
-           if(HwInfo->jChipType == SIS_740) {
+           if(SiS_Pr->ChipType == SIS_740) {
               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x03);
            } else {
              SiS_SetReg(SiS_Pr->SiS_Part1Port,0x1e,0x23);
@@ -6061,17 +5868,26 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
 #ifdef SIS300
   if(SiS_Pr->SiS_IF_DEF_TRUMPION) {
-     int i;
-     UCHAR TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
-     UCHAR TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
-     UCHAR TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+     unsigned char *ROMAddr = SiS_Pr->VirtualRomBase;
+     unsigned char *trumpdata;
+     int   i, j = crt2crtc;
+     unsigned char TrumpMode13[4]   = { 0x01, 0x10, 0x2c, 0x00 };
+     unsigned char TrumpMode10_1[4] = { 0x01, 0x10, 0x27, 0x00 };
+     unsigned char TrumpMode10_2[4] = { 0x01, 0x16, 0x10, 0x00 };
+
+     if(SiS_Pr->SiS_UseROM) {
+       trumpdata = &ROMAddr[0x8001 + (j * 80)];
+     } else {
+       if(SiS_Pr->SiS_LCDTypeInfo == 0x0e) j += 7;
+       trumpdata = &SiS300_TrumpionData[j][0];
+     }
 
      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xbf);
      for(i=0; i<5; i++) {
-        SiS_SetTrumpionBlock(SiS_Pr, &SiS300_TrumpionData[crt2crtc][0]);
+       SiS_SetTrumpionBlock(SiS_Pr, trumpdata);
      }
      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-        if(ModeNo == 0x13) {
+       if(ModeNo == 0x13) {
           for(i=0; i<4; i++) {
              SiS_SetTrumpionBlock(SiS_Pr, &TrumpMode13[0]);
           }
@@ -6095,67 +5911,66 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x29,0x5A);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2A,0x4B);
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x07,0x03);
-     tempax = SiS_Pr->SiS_HDE;                                 /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
-     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
+     tempax = SiS_Pr->SiS_HDE;                                 /* Blps = lcdhdee(lcdhdes+HDE) + 64 */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
      tempax += 64;
-     temp = tempax & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,temp);
-     temp = ((tempax & 0xFF00) >> 8) << 3;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x38,tempax & 0xff);
+     temp = (tempax >> 8) << 3;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x35,~0x078,temp);
-     tempax += 32;                                             /* Blpe=lBlps+32 */
-     temp = tempax & 0x00FF;
-     if(SiS_Pr->SiS_IF_DEF_FSTN) temp = 0;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,temp);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);              /* Bflml=0 */
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x007,0x00);
+     tempax += 32;                                             /* Blpe = lBlps+32 */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x39,tempax & 0xff);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3A,0x00);              /* Bflml = 0 */
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x007);
 
      tempax = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
      tempax >>= 1;
-     temp = tempax & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,temp);
-     temp = ((tempax & 0xFF00) >> 8) << 3;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3B,tempax & 0xff);
+     temp = (tempax >> 8) << 3;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x038,temp);
 
      tempeax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempeax >>= 1;
-     tempeax <<= 2;                                            /* BDxFIFOSTOP = (HDE*4)/128 */
-     tempebx = 128;
-     temp = (USHORT)(tempeax % tempebx);
-     tempeax = tempeax / tempebx;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempeax >>= 1;
+     tempeax <<= 2;                                            /* BDxFIFOSTOP = (HDE*4)/128 */
+     temp = tempeax & 0x7f;
+     tempeax >>= 7;
      if(temp) tempeax++;
-     temp = (USHORT)(tempeax & 0x003F);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x45,~0x0FF,temp);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);              /* BDxWadrst0 */
+     temp = tempeax & 0x3f;
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x45,temp);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3F,0x00);              /* BDxWadrst0 */
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3E,0x00);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x3D,0x10);
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x040,0x00);
+     SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x3C,~0x040);
 
      tempax = SiS_Pr->SiS_HDE;
-     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
-     tempax >>= 4;                                             /* BDxWadroff = HDE*4/8/8 */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+     tempax >>= 4;                                             /* BDxWadroff = HDE*4/8/8 */
      pushcx = tempax;
      temp = tempax & 0x00FF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x43,temp);
      temp = ((tempax & 0xFF00) >> 8) << 3;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x44,~0x0F8,temp);
 
-     tempax = SiS_Pr->SiS_VDE;                                 /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
-     if(SiS_Pr->SiS_LCDResInfo == Panel_640x480_2 ||
-        SiS_Pr->SiS_LCDResInfo == Panel_640x480_3) tempax >>= 1;
-     tempeax = (tempax * pushcx);
-     tempebx = 0x00100000 + tempeax;
-     temp = (USHORT)tempebx & 0x000000FF;
+     tempax = SiS_Pr->SiS_VDE;                                 /* BDxWadrst1 = BDxWadrst0 + BDxWadroff * VDE */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_320x240_1 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_2 ||
+        SiS_Pr->SiS_LCDResInfo == Panel_320x240_3) tempax >>= 1;
+     tempeax = tempax * pushcx;
+     temp = tempeax & 0xFF;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x42,temp);
-     temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
+     temp = (tempeax & 0xFF00) >> 8;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x41,temp);
-     temp = (USHORT)((tempebx & 0x00FF0000) >> 16);
+     temp = ((tempeax & 0xFF0000) >> 16) | 0x10;
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x40,temp);
-     temp = (USHORT)(((tempebx & 0x01000000) >> 24) << 7);
+     temp = ((tempeax & 0x01000000) >> 24) << 7;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x3C,~0x080,temp);
 
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2F,0x03);
@@ -6192,20 +6007,20 @@ SiS_SetGroup1_LVDS(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
 /* Set Part 1 */
 static void
-SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-              PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
+SiS_SetGroup1(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
 {
 #if defined(SIS300) || defined(SIS315H)
-  UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
+  unsigned char   *ROMAddr = SiS_Pr->VirtualRomBase;
 #endif
-  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
-  USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
+  unsigned short  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
+  unsigned short  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
 #ifdef SIS315H
-  USHORT  tempbl=0;
+  unsigned short  tempbl=0;
 #endif
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
      return;
   }
 
@@ -6214,47 +6029,47 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   } else if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
   } else {
-     CRT1Index = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+     CRT1Index = SiS_GetRefCRT1CRTC(SiS_Pr, RefreshRateTableIndex, SiS_Pr->SiS_UseWideCRT2);
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
   }
 
-  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+  SiS_SetCRT2Offset(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 
-  if( ! ((HwInfo->jChipType >= SIS_315H) &&
+  if( ! ((SiS_Pr->ChipType >= SIS_315H) &&
          (SiS_Pr->SiS_IF_DEF_LVDS == 1) &&
          (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ) {
 
-     if(HwInfo->jChipType < SIS_315H ) {
+     if(SiS_Pr->ChipType < SIS_315H ) {
 #ifdef SIS300
-       SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo, HwInfo);
+       SiS_SetCRT2FIFO_300(SiS_Pr, ModeNo);
 #endif
      } else {
 #ifdef SIS315H
-        SiS_SetCRT2FIFO_310(SiS_Pr, HwInfo);
+       SiS_SetCRT2FIFO_310(SiS_Pr);
 #endif
      }
 
      /* 1. Horizontal setup */
 
-     if(HwInfo->jChipType < SIS_315H ) {
+     if(SiS_Pr->ChipType < SIS_315H ) {
 
 #ifdef SIS300   /* ------------- 300 series --------------*/
 
-       temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
-       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
+       temp = (SiS_Pr->SiS_VGAHT - 1) & 0x0FF;                   /* BTVGA2HT 0x08,0x09 */
+       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
 
-       temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
-       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
+       temp = (((SiS_Pr->SiS_VGAHT - 1) & 0xFF00) >> 8) << 4;
+       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0f,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
-       temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
-       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
+       temp = (SiS_Pr->SiS_VGAHDE + 12) & 0x0FF;                 /* BTVGA2HDEE 0x0A,0x0C */
+       SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
 
        pushbx = SiS_Pr->SiS_VGAHDE + 12;                         /* bx  BTVGA2HRS 0x0B,0x0C */
-       tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
-       tempbx = pushbx + tempcx;
-       tempcx <<= 1;
-       tempcx += tempbx;
+       tempcx = (SiS_Pr->SiS_VGAHT - SiS_Pr->SiS_VGAHDE) >> 2;
+       tempbx = pushbx + tempcx;
+       tempcx <<= 1;
+       tempcx += tempbx;
 
        bridgeadd = 12;
 
@@ -6301,7 +6116,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
        bridgeadd = 16;
 
        if(SiS_Pr->SiS_VBType & VB_SISVB) {
-          if(HwInfo->jChipType >= SIS_661) {
+          if(SiS_Pr->ChipType >= SIS_661) {
              if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
                 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
                 if(resinfo == SIS_RI_1280x1024) {
@@ -6319,7 +6134,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
      if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-        if(SiS_Pr->UseCustomMode) {
+       if(SiS_Pr->UseCustomMode) {
           tempbx = SiS_Pr->CHSyncStart + bridgeadd;
           tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
           tempax = SiS_Pr->SiS_VGAHT;
@@ -6341,22 +6156,22 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
              cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
              cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
           }
-           tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3;               /* (VGAHRS-3)*8 */
-           tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
+          tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3;                /* (VGAHRS-3)*8 */
+          tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
           tempcx &= 0x00FF;
           tempcx |= (tempbx & 0xFF00);
-           tempbx += bridgeadd;
-           tempcx += bridgeadd;
+          tempbx += bridgeadd;
+          tempcx += bridgeadd;
           tempax = SiS_Pr->SiS_VGAHT;
           if(modeflag & HalfDCLK) tempax >>= 1;
           tempax--;
           if(tempcx > tempax) tempcx = tempax;
-        }
+       }
 
-        if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-          tempbx = 1040;
-          tempcx = 1044;   /* HWCursor bug! */
-        }
+       if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
+          tempbx = 1040;
+          tempcx = 1044;   /* HWCursor bug! */
+       }
 
      }
 
@@ -6372,18 +6187,18 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      tempcx = SiS_Pr->SiS_VGAVT - 1;
      temp = tempcx & 0x00FF;
 
-     if(HwInfo->jChipType < SIS_661) {
+     if(SiS_Pr->ChipType < SIS_661) {
         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-          if(HwInfo->jChipType < SIS_315H) {
+          if(SiS_Pr->ChipType < SIS_315H) {
              if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
                 if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
                    temp--;
                 }
-              }
+             }
           } else {
-             temp--;
-           }
-        } else if(HwInfo->jChipType >= SIS_315H) {
+             temp--;
+          }
+       } else if(SiS_Pr->ChipType >= SIS_315H) {
           temp--;
        }
      }
@@ -6395,9 +6210,9 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
 
-     if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-        tempbx++;
-       tempax = tempbx;
+     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->ChipType < SIS_661)) {
+       tempbx++;
+       tempax = tempbx;
        tempcx++;
        tempcx -= tempax;
        tempcx >>= 2;
@@ -6407,8 +6222,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
        tempcx += tempbx;
        tempcx++;
      } else {
-       tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
-       tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
+       tempbx = (SiS_Pr->SiS_VGAVT + SiS_Pr->SiS_VGAVDE) >> 1;                 /*  BTVGA2VRS     0x10,0x11   */
+       tempcx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) >> 4) + tempbx + 1;  /*  BTVGA2VRE     0x11        */
      }
 
      if(SiS_Pr->SiS_VBType & VB_SISVB) {
@@ -6416,7 +6231,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
           tempbx = SiS_Pr->CVSyncStart;
           tempcx = SiS_Pr->CVSyncEnd;
        }
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+       if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
           unsigned char cr8, cr7, cr13;
           if(SiS_Pr->UseCustomMode) {
              cr8    = SiS_Pr->CCRT1CRTC[8];
@@ -6429,11 +6244,11 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
              cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
              tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
           }
-          tempbx = cr8;
-          if(cr7  & 0x04) tempbx |= 0x0100;
-          if(cr7  & 0x80) tempbx |= 0x0200;
-          if(cr13 & 0x08) tempbx |= 0x0400;
-               }
+          tempbx = cr8;
+          if(cr7  & 0x04) tempbx |= 0x0100;
+          if(cr7  & 0x80) tempbx |= 0x0200;
+          if(cr13 & 0x08) tempbx |= 0x0400;
+       }
      }
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
 
@@ -6442,13 +6257,13 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
      /* 3. Panel delay compensation */
 
-     if(HwInfo->jChipType < SIS_315H) {
+     if(SiS_Pr->ChipType < SIS_315H) {
 
 #ifdef SIS300  /* ---------- 300 series -------------- */
 
        if(SiS_Pr->SiS_VBType & VB_SISVB) {
           temp = 0x20;
-          if(HwInfo->jChipType == SIS_300) {
+          if(SiS_Pr->ChipType == SIS_300) {
              temp = 0x10;
              if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
              if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) temp = 0x20;
@@ -6460,24 +6275,23 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
           if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)             temp = 0x08;
           if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-             if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)       temp = 0x2c;
-             else                                          temp = 0x20;
-          }
+             if(SiS_Pr->SiS_VBInfo & SetInSlaveMode)       temp = 0x2c;
+             else                                          temp = 0x20;
+          }
           if(SiS_Pr->SiS_UseROM) {
              if(ROMAddr[0x220] & 0x80) {
-                if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
-                   temp = ROMAddr[0x221];
+                if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision)
+                   temp = ROMAddr[0x221];
                 else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)
                    temp = ROMAddr[0x222];
                 else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)
                    temp = ROMAddr[0x223];
                 else
                    temp = ROMAddr[0x224];
-                temp &= 0x3c;
              }
           }
           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-             if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC & 0x3c;
+             if(SiS_Pr->PDC != -1)  temp = SiS_Pr->PDC;
           }
 
        } else {
@@ -6487,15 +6301,17 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
           }
           if(SiS_Pr->SiS_UseROM) {
              if(ROMAddr[0x220] & 0x80) {
-                temp = ROMAddr[0x220] & 0x3c;
+                temp = ROMAddr[0x220];
              }
           }
           if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-             if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC & 0x3c;
+             if(SiS_Pr->PDC != -1) temp = SiS_Pr->PDC;
           }
-        }
+       }
 
-       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
+       temp &= 0x3c;
+
+       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,~0x3C,temp);   /* Panel Link Delay Compensation; (Software Command Reset; Power Saving) */
 
 #endif  /* SIS300 */
 
@@ -6503,16 +6319,16 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
 #ifdef SIS315H   /* --------------- 315/330 series ---------------*/
 
-        if(HwInfo->jChipType < SIS_661) {
+       if(SiS_Pr->ChipType < SIS_661) {
 
           if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
 
-             if(HwInfo->jChipType == SIS_740) temp = 0x03;
-             else                             temp = 0x00;
+             if(SiS_Pr->ChipType == SIS_740) temp = 0x03;
+             else                            temp = 0x00;
 
              if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) temp = 0x0a;
              tempbl = 0xF0;
-             if(HwInfo->jChipType == SIS_650) {
+             if(SiS_Pr->ChipType == SIS_650) {
                 if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
                    if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempbl = 0x0F;
                 }
@@ -6531,10 +6347,10 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
        } /* < 661 */
 
-       tempax = 0;
-       if(modeflag & DoubleScanMode) tempax |= 0x80;
-       if(modeflag & HalfDCLK)       tempax |= 0x40;
-       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
+       tempax = 0;
+       if(modeflag & DoubleScanMode) tempax |= 0x80;
+       if(modeflag & HalfDCLK)       tempax |= 0x40;
+       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
 #endif  /* SIS315H */
 
@@ -6544,21 +6360,21 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-        /* For 301BDH with LCD, we set up the Panel Link */
-       SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+       /* For 301BDH with LCD, we set up the Panel Link */
+       SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
      } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-       SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+       SiS_SetGroup1_301(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
      }
   } else {
-     if(HwInfo->jChipType < SIS_315H) {
-       SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+     if(SiS_Pr->ChipType < SIS_315H) {
+       SiS_SetGroup1_LVDS(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
      } else {
        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-           if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-             SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
-           }
+          if((!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) || (SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
+             SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
+          }
        } else {
-          SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex, HwInfo,RefreshRateTableIndex);
+          SiS_SetGroup1_LVDS(SiS_Pr, ModeNo,ModeIdIndex,RefreshRateTableIndex);
        }
      }
   }
@@ -6569,11 +6385,11 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 #ifdef SIS315H
-static UCHAR *
-SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
+static unsigned char *
+SiS_GetGroup2CLVXPtr(struct SiS_Private *SiS_Pr, int tabletype)
 {
-   const UCHAR  *tableptr = NULL;
-   USHORT       a, b, p = 0;
+   const unsigned char *tableptr = NULL;
+   unsigned short      a, b, p = 0;
 
    a = SiS_Pr->SiS_VGAHDE;
    b = SiS_Pr->SiS_HDE;
@@ -6606,25 +6422,25 @@ SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr, int tabletype, PSIS_HW_INFO HwInfo)
       if((tableptr[p] | tableptr[p+1] << 8) == 0xffff) p -= 0x42;
    }
    p += 2;
-   return((UCHAR *)&tableptr[p]);
+   return ((unsigned char *)&tableptr[p]);
 }
 
 static void
-SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetGroup2_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                   unsigned short RefreshRateTableIndex)
 {
-   UCHAR *tableptr;
+   unsigned char *tableptr;
+   unsigned char temp;
    int i, j;
-   UCHAR temp;
 
-   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+   if(!(SiS_Pr->SiS_VBType & VB_SISTAP4SCALER)) return;
 
-   tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0, HwInfo);
+   tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 0);
    for(i = 0x80, j = 0; i <= 0xbf; i++, j++) {
       SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
    }
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-      tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1, HwInfo);
+      tableptr = SiS_GetGroup2CLVXPtr(SiS_Pr, 1);
       for(i = 0xc0, j = 0; i <= 0xff; i++, j++) {
          SiS_SetReg(SiS_Pr->SiS_Part2Port, i, tableptr[j]);
       }
@@ -6635,12 +6451,12 @@ SiS_SetGroup2_C_ELV(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 }
 
 static BOOLEAN
-SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
-                   USHORT RefreshRateTableIndex,USHORT *CRT2Index,
-                   USHORT *ResIndex,PSIS_HW_INFO HwInfo)
+SiS_GetCRT2Part2Ptr(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex,
+                   unsigned short RefreshRateTableIndex,unsigned short *CRT2Index,
+                   unsigned short *ResIndex)
 {
 
-  if(HwInfo->jChipType < SIS_315H) return FALSE;
+  if(SiS_Pr->ChipType < SIS_315H) return FALSE;
 
   if(ModeNo <= 0x13)
      (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
@@ -6661,82 +6477,79 @@ SiS_GetCRT2Part2Ptr(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex,
         if(SiS_Pr->SiS_SetFlag & LCDVESATiming) (*CRT2Index) = 206;
      }
   }
-  return(((*CRT2Index) != 0));
+  return (((*CRT2Index) != 0));
 }
 #endif
 
 #ifdef SIS300
 static void
-SiS_Group2LCDSpecial(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT crt2crtc)
+SiS_Group2LCDSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short crt2crtc)
 {
-   USHORT tempcx;
-   const UCHAR atable[] = {
+   unsigned short tempcx;
+   static const unsigned char atable[] = {
        0xc3,0x9e,0xc3,0x9e,0x02,0x02,0x02,
        0xab,0x87,0xab,0x9e,0xe7,0x02,0x02
    };
 
    if(!SiS_Pr->UseCustomMode) {
-      if( ( ( (HwInfo->jChipType == SIS_630) ||
-              (HwInfo->jChipType == SIS_730) ) &&
-            (HwInfo->jChipRevision > 2) )  &&
-          (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
-          (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
-          (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
-         if(ModeNo == 0x13) {
-            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
-            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
-            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
-         } else {
-            if((crt2crtc & 0x3F) == 4) {
-               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
-               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
-               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
-               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
-               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
-            }
-         }
+      if( ( ( (SiS_Pr->ChipType == SIS_630) ||
+             (SiS_Pr->ChipType == SIS_730) ) &&
+           (SiS_Pr->ChipRevision > 2) )  &&
+         (SiS_Pr->SiS_LCDResInfo == Panel_1024x768) &&
+         (!(SiS_Pr->SiS_SetFlag & LCDVESATiming))  &&
+         (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) ) {
+        if(ModeNo == 0x13) {
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xB9);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0xCC);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xA6);
+        } else if((crt2crtc & 0x3F) == 4) {
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x2B);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x13);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,0xE5);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,0x08);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xE2);
+        }
       }
 
-      if(HwInfo->jChipType < SIS_315H) {
-         if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
-            crt2crtc &= 0x1f;
-            tempcx = 0;
-            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                  tempcx += 7;
-               }
-            }
-            tempcx += crt2crtc;
-            if(crt2crtc >= 4) {
-               SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
-            }
+      if(SiS_Pr->ChipType < SIS_315H) {
+        if(SiS_Pr->SiS_LCDTypeInfo == 0x0c) {
+           crt2crtc &= 0x1f;
+           tempcx = 0;
+           if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                 tempcx += 7;
+              }
+           }
+           tempcx += crt2crtc;
+           if(crt2crtc >= 4) {
+              SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,0xff);
+           }
 
-            if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
-               if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                  if(crt2crtc == 4) {
-                     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
-                  }
-               }
-            }
-            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
-            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
-         }
+           if(!(SiS_Pr->SiS_VBInfo & SetNotSimuMode)) {
+              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                 if(crt2crtc == 4) {
+                    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x28);
+                 }
+              }
+           }
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x18);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,atable[tempcx]);
+        }
       }
    }
 }
 
 /* For ECS A907. Highly preliminary. */
 static void
-SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                   USHORT ModeIdIndex, USHORT RefreshRateTableIndex,
-                   USHORT ModeNo)
+SiS_Set300Part2Regs(struct SiS_Private *SiS_Pr, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex,
+                   unsigned short ModeNo)
 {
-  USHORT crt2crtc, resindex;
-  int    i,j;
-  const  SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
+  unsigned short crt2crtc, resindex;
+  int i, j;
 
-  if(HwInfo->jChipType != SIS_300) return;
-  if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
+  if(SiS_Pr->ChipType != SIS_300) return;
+  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
   if(SiS_Pr->UseCustomMode) return;
 
   if(ModeNo <= 0x13) {
@@ -6758,13 +6571,13 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x02,0x80,(CRT2Part2Ptr+resindex)->CR[1]);
   for(i = 2, j = 0x04; j <= 0x06; i++, j++ ) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
   }
   for(j = 0x1c; j <= 0x1d; i++, j++ ) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
   }
   for(j = 0x1f; j <= 0x21; i++, j++ ) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,j,(CRT2Part2Ptr+resindex)->CR[i]);
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,(CRT2Part2Ptr+resindex)->CR[10]);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0f,(CRT2Part2Ptr+resindex)->CR[11]);
@@ -6772,15 +6585,15 @@ SiS_Set300Part2Regs(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 #endif
 
 static void
-SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SetTVSpecial(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-  if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) return;
+  if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV)) return;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) return;
   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) return;
 
   if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
      if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-        const UCHAR specialtv[] = {
+        const unsigned char specialtv[] = {
                0xa7,0x07,0xf2,0x6e,0x17,0x8b,0x73,0x53,
                0x13,0x40,0x34,0xf4,0x63,0xbb,0xcc,0x7a,
                0x58,0xe4,0x73,0xda,0x13
@@ -6813,16 +6626,16 @@ SiS_SetTVSpecial(SiS_Private *SiS_Pr, USHORT ModeNo)
 }
 
 static void
-SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
+SiS_SetGroup2_Tail(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-  USHORT temp;
+  unsigned short temp;
 
   if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) {
      if(SiS_Pr->SiS_VGAVDE == 525) {
        temp = 0xc3;
        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
           temp++;
-          if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp += 2;
+          if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp += 2;
        }
        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,0xb3);
@@ -6830,7 +6643,7 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
        temp = 0x4d;
        if(SiS_Pr->SiS_ModeType <= ModeVGA) {
           temp++;
-          if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) temp++;
+          if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) temp++;
        }
        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2f,temp);
      }
@@ -6838,7 +6651,7 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
      if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) {
-       if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+       if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
           SiS_SetRegOR(SiS_Pr->SiS_Part2Port,0x1a,0x03);
           /* Not always for LV, see SetGrp2 */
        }
@@ -6872,17 +6685,17 @@ SiS_SetGroup2_Tail(SiS_Private *SiS_Pr, USHORT ModeNo)
 }
 
 static void
-SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
-             PSIS_HW_INFO HwInfo)
-{
-  USHORT      i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
-  USHORT      push2, modeflag, crt2crtc, bridgeoffset;
-  ULONG       longtemp;
-  const       UCHAR *PhasePoint;
-  const       UCHAR *TimingPoint;
+SiS_SetGroup2(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
+{
+  unsigned short i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+  unsigned short push2, modeflag, crt2crtc, bridgeoffset;
+  unsigned int   longtemp, PhaseIndex;
+  BOOLEAN        newtvphase;
+  const unsigned char *TimingPoint;
 #ifdef SIS315H
-  USHORT      resindex, CRT2Index;
-  const       SiS_Part2PortTblStruct *CRT2Part2Ptr = NULL;
+  unsigned short resindex, CRT2Index;
+  const struct SiS_Part2PortTbl *CRT2Part2Ptr = NULL;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 #endif
@@ -6908,9 +6721,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x00,temp);
 
-  PhasePoint  = SiS_Pr->SiS_PALPhase;
+  PhaseIndex  = 0x01; /* SiS_PALPhase */
   TimingPoint = SiS_Pr->SiS_PALTiming;
 
+  newtvphase = FALSE;
+  if( (SiS_Pr->SiS_VBType & VB_SIS30xBLV) &&
+      ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
+       (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
+     newtvphase = TRUE;
+  }
+
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 
      TimingPoint = SiS_Pr->SiS_HiTVExtTiming;
@@ -6918,82 +6738,54 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
         TimingPoint = SiS_Pr->SiS_HiTVSt2Timing;
         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
           TimingPoint = SiS_Pr->SiS_HiTVSt1Timing;
-#if 0
-           if(!(modeflag & Charx8Dot))  TimingPoint = SiS_Pr->SiS_HiTVTextTiming;
-#endif
         }
      }
 
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
 
-     if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      TimingPoint = &SiS_YPbPrTable[2][0];
-     else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) TimingPoint = &SiS_YPbPrTable[1][0];
-     else                                        TimingPoint = &SiS_YPbPrTable[0][0];
+     i = 0;
+     if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)      i = 2;
+     else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) i = 1;
 
-     PhasePoint = SiS_Pr->SiS_NTSCPhase;
+     TimingPoint = &SiS_YPbPrTable[i][0];
+
+     PhaseIndex = 0x00; /* SiS_NTSCPhase */
 
   } else if(SiS_Pr->SiS_TVMode & TVSetPAL) {
 
-     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-         ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-        PhasePoint = SiS_Pr->SiS_PALPhase2;
-     }
+     if(newtvphase) PhaseIndex = 0x09; /* SiS_PALPhase2 */
 
   } else {
 
      TimingPoint = SiS_Pr->SiS_NTSCTiming;
-     PhasePoint  = SiS_Pr->SiS_NTSCPhase;
-     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-       PhasePoint = SiS_Pr->SiS_PALPhase;
-     }
-
-     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-        ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-        PhasePoint = SiS_Pr->SiS_NTSCPhase2;
-       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-          PhasePoint = SiS_Pr->SiS_PALPhase2;
-       }
-     }
-
-  }
+     PhaseIndex  = (SiS_Pr->SiS_TVMode & TVSetNTSCJ) ? 0x01 : 0x00;    /* SiS_PALPhase : SiS_NTSCPhase */
+     if(newtvphase) PhaseIndex += 8;                                   /* SiS_PALPhase2 : SiS_NTSCPhase2 */
 
-  if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-     PhasePoint = SiS_Pr->SiS_PALMPhase;
-     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-        ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-        PhasePoint = SiS_Pr->SiS_PALMPhase2;
-     }
   }
 
-  if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-     PhasePoint = SiS_Pr->SiS_PALNPhase;
-     if( (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) &&
-        ( (!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
-          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode) ) ) {
-       PhasePoint = SiS_Pr->SiS_PALNPhase2;
-     }
+  if(SiS_Pr->SiS_TVMode & (TVSetPALM | TVSetPALN)) {
+     PhaseIndex = (SiS_Pr->SiS_TVMode & TVSetPALM) ? 0x02 : 0x03;      /* SiS_PALMPhase : SiS_PALNPhase */
+     if(newtvphase) PhaseIndex += 8;                                   /* SiS_PALMPhase2 : SiS_PALNPhase2 */
   }
 
   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-     PhasePoint = SiS_Pr->SiS_SpecialPhase;
      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-        PhasePoint = SiS_Pr->SiS_SpecialPhaseM;
+        PhaseIndex = 0x05; /* SiS_SpecialPhaseM */
      } else if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-        PhasePoint = SiS_Pr->SiS_SpecialPhaseJ;
+        PhaseIndex = 0x11; /* SiS_SpecialPhaseJ */
+     } else {
+        PhaseIndex = 0x10; /* SiS_SpecialPhase */
      }
   }
 
-  for(i=0x31, j=0; i<=0x34; i++, j++) {
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,PhasePoint[j]);
+  for(i = 0x31, j = 0; i <= 0x34; i++, j++) {
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[(PhaseIndex * 4) + j]);
   }
 
-  for(i=0x01, j=0; i<=0x2D; i++, j++) {
+  for(i = 0x01, j = 0; i <= 0x2D; i++, j++) {
      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
   }
-  for(i=0x39; i<=0x45; i++, j++) {
+  for(i = 0x39; i <= 0x45; i++, j++) {
      SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
   }
 
@@ -7010,28 +6802,32 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x37,SiS_Pr->SiS_RY3COE);
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x38,SiS_Pr->SiS_RY4COE);
 
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)   tempax = 950;
-  else if(SiS_Pr->SiS_TVMode & TVSetPAL)       tempax = 520;
-  else                                                 tempax = 440; /* NTSC, YPbPr 525, 750 */
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision)   tempax = 950;
+  else if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p)  tempax = 680;
+  else if(SiS_Pr->SiS_TVMode & TVSetPAL)       tempax = 520;
+  else                                         tempax = 440; /* NTSC, YPbPr 525 */
 
-  if( ( (!(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision)) && (SiS_Pr->SiS_VDE <= tempax) ) ||
+  if( ((SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) && (SiS_Pr->SiS_VDE <= tempax)) ||
       ( (SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoHiVision) &&
         ((SiS_Pr->SiS_VGAHDE == 1024) || (SiS_Pr->SiS_VDE <= tempax)) ) ) {
 
      tempax -= SiS_Pr->SiS_VDE;
-     tempax >>= 2;
+     tempax >>= 1;
+     if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
+        tempax >>= 1;
+     }
      tempax &= 0x00ff;
 
-     temp = tempax + (USHORT)TimingPoint[0];
+     temp = tempax + (unsigned short)TimingPoint[0];
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
 
-     temp = tempax + (USHORT)TimingPoint[1];
+     temp = tempax + (unsigned short)TimingPoint[1];
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
      if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) && (SiS_Pr->SiS_VGAHDE >= 1024)) {
         if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);  /* 19 */
-           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);  /* 52 */
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x1b);
+           SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x54);
         } else {
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,0x17);
            SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,0x1d);
@@ -7041,14 +6837,14 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   }
 
   tempcx = SiS_Pr->SiS_HT;
-  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
   tempcx--;
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) tempcx--;
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
 
   tempcx = SiS_Pr->SiS_HT >> 1;
-  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
   tempcx += 7;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
@@ -7075,7 +6871,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
 
   tempcx = SiS_Pr->SiS_HT >> 1;
-  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempcx >>= 1;
   j += 2;
   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
@@ -7094,7 +6890,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
              (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
      tempbx >>= 1;
-     if(HwInfo->jChipType >= SIS_315H) {
+     if(SiS_Pr->ChipType >= SIS_315H) {
         if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
           if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
        } else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
@@ -7123,23 +6919,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
 
-  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+  if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
   }
 
-#if 0
-  /* TEST qqqq */
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
-     for(i=0x01, j=0; i<=0x2D; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
-     }
-     for(i=0x39; i<=0x45; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
-     }
-  }
-#endif
-
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
      tempbx = SiS_Pr->SiS_VDE;
      if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
          (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
@@ -7150,7 +6934,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
 
-     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+     if(SiS_Pr->SiS_VBType & VB_SISPART4OVERFLOW) {
        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
      }
   }
@@ -7165,14 +6949,17 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
   tempch = tempcl = 0x01;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(SiS_Pr->SiS_VGAHDE >= 1024) {
-        if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
-           tempch = 0x19;
+     if(SiS_Pr->SiS_VGAHDE >= 960) {
+        if((!(modeflag & HalfDCLK)) || (SiS_Pr->ChipType < SIS_315H)) {
           tempcl = 0x20;
-           if(SiS_Pr->SiS_VGAHDE >= 1280) {
-              tempch = 0x14;
+          if(SiS_Pr->SiS_VGAHDE >= 1280) {
+              tempch = 20;
               tempbx &= ~0x20;
-           }
+           } else if(SiS_Pr->SiS_VGAHDE >= 1024) {
+              tempch = 25;
+           } else {
+             tempch = 25; /* OK */
+          }
         }
      }
   }
@@ -7180,7 +6967,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   if(!(tempbx & 0x20)) {
      if(modeflag & HalfDCLK) tempcl <<= 1;
      longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) longtemp <<= 3;
      tempax = longtemp / SiS_Pr->SiS_HDE;
      if(longtemp % SiS_Pr->SiS_HDE) tempax++;
      tempbx |= ((tempax >> 8) & 0x1F);
@@ -7190,7 +6977,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 
      tempcx &= 0x07;
      if(tempbx & 0x20) tempcx = 0;
@@ -7219,7 +7006,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
      SiS_SetTVSpecial(SiS_Pr, ModeNo);
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
         temp = 0;
         if(SiS_Pr->SiS_TVMode & TVSetPALM) temp = 8;
         SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x4e,0xf7,temp);
@@ -7246,7 +7033,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
   /* From here: Part2 LCD setup */
 
   tempbx = SiS_Pr->SiS_HDE;
-  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
   tempbx--;                                    /* RHACTE = HDE - 1 */
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
@@ -7256,10 +7043,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
      if(SiS_Pr->SiS_ModeType == ModeEGA) {
         if(SiS_Pr->SiS_VGAHDE >= 1024) {
            temp = 0x02;
-          if(HwInfo->jChipType >= SIS_315H) {
-              if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
-                 temp = 0x01;
-             }
+           if(SiS_Pr->SiS_SetFlag & LCDVESATiming) {
+              temp = 0x01;
           }
         }
      }
@@ -7289,11 +7074,11 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
 #ifdef SIS315H
   if(SiS_GetCRT2Part2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                                               &CRT2Index, &resindex, HwInfo)) {
+                                               &CRT2Index, &resindex)) {
       switch(CRT2Index) {
+        case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
+       default:
         case 200: CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_1;   break;
-       case 206: CRT2Part2Ptr = SiS310_CRT2Part2_Asus1024x768_3;    break;
-       default:  CRT2Part2Ptr = SiS_Pr->SiS_CRT2Part2_1024x768_3;   break;
       }
 
       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x01,0x80,(CRT2Part2Ptr+resindex)->CR[0]);
@@ -7312,7 +7097,6 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
       SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
-
   } else {
 #endif
 
@@ -7349,8 +7133,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
     /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
+#endif
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);     /* lcdvdes  */
@@ -7401,8 +7187,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
        tempbx = SiS_Pr->CVSyncStart;
     }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdvrs 0x%x\n", tempbx);
+#endif
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);         /* lcdvrs */
@@ -7416,26 +7204,30 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
        temp |= (SiS_Pr->CVSyncEnd & 0x0f);
     }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdvre[3:0] 0x%x\n", (temp & 0x0f));
+#endif
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp);
 
 #ifdef SIS300
-    SiS_Group2LCDSpecial(SiS_Pr, HwInfo, ModeNo, crt2crtc);
+    SiS_Group2LCDSpecial(SiS_Pr, ModeNo, crt2crtc);
 #endif
 
     bridgeoffset = 7;
-    if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)          bridgeoffset += 2;
-    if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) bridgeoffset++;
-    if(SiS_IsDualLink(SiS_Pr, HwInfo))                  bridgeoffset++;
+    if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)      bridgeoffset += 2;
+    if(SiS_Pr->SiS_VBType & VB_SIS30xCLV)      bridgeoffset += 2; /* OK for Averatec 1280x800 (301C) */
+    if(SiS_IsDualLink(SiS_Pr))                 bridgeoffset++;
+    else if(SiS_Pr->SiS_VBType & VB_SIS302LV)  bridgeoffset++;    /* OK for Asus A4L 1280x800 */
+    /* Higher bridgeoffset shifts to the LEFT */
 
     temp = 0;
     if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
        if(SiS_Pr->PanelXRes != SiS_Pr->SiS_HDE) {
-          temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
-         if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp >>= 1;
+         temp = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
+         if(SiS_IsDualLink(SiS_Pr)) temp >>= 1;
        }
     }
     temp += bridgeoffset;
@@ -7450,14 +7242,16 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
           tempbx = SiS_Pr->PanelXRes - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_HDE) / 2);
        }
     }
-    if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
+    if(SiS_IsDualLink(SiS_Pr)) {
        tempcx >>= 1;
        tempbx >>= 1;
        tempax >>= 1;
     }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhdee 0x%x\n", tempbx);
+#endif
 #endif
 
     tempbx += bridgeoffset;
@@ -7480,12 +7274,15 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
     if(SiS_Pr->UseCustomMode) {
        tempbx = SiS_Pr->CHSyncStart;
-       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       if(modeflag & HalfDCLK) tempbx <<= 1;
+       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
        tempbx += bridgeoffset;
     }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhrs 0x%x\n", tempbx);
+#endif
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);         /* lcdhrs */
@@ -7501,12 +7298,15 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 
     if(SiS_Pr->UseCustomMode) {
        tempbx = SiS_Pr->CHSyncEnd;
-       if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+       if(modeflag & HalfDCLK) tempbx <<= 1;
+       if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
        tempbx += bridgeoffset;
     }
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdhre 0x%x\n", tempbx);
+#endif
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x21,tempbx);         /* lcdhre */
@@ -7514,7 +7314,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
     SiS_SetGroup2_Tail(SiS_Pr, ModeNo);
 
 #ifdef SIS300
-    SiS_Set300Part2Regs(SiS_Pr, HwInfo, ModeIdIndex, RefreshRateTableIndex, ModeNo);
+    SiS_Set300Part2Regs(SiS_Pr, ModeIdIndex, RefreshRateTableIndex, ModeNo);
 #endif
 #ifdef SIS315H
   } /* CRT2-LCD from table */
@@ -7526,11 +7326,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT Refr
 /*********************************************/
 
 static void
-SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-              PSIS_HW_INFO HwInfo)
+SiS_SetGroup3(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  USHORT       i;
-  const UCHAR          *tempdi;
+  unsigned short i;
+  const unsigned char *tempdi;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) return;
 
@@ -7570,7 +7369,7 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      for(i=0; i<=0x3E; i++) {
         SiS_SetReg(SiS_Pr->SiS_Part3Port,i,tempdi[i]);
      }
-     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV)) {
+     if(SiS_Pr->SiS_VBType & VB_SIS30xCLV) {
        if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
           SiS_SetReg(SiS_Pr->SiS_Part3Port,0x28,0x3f);
        }
@@ -7587,35 +7386,43 @@ SiS_SetGroup3(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 #ifdef SIS315H
+#if 0
 static void
-SiS_ShiftXPos(SiS_Private *SiS_Pr, int shift)
+SiS_ShiftXPos(struct SiS_Private *SiS_Pr, int shift)
 {
-   USHORT temp, temp1, temp2;
+   unsigned short temp, temp1, temp2;
 
    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x1f);
    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x20);
-   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1f,temp);
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0f,((temp >> 4) & 0xf0));
    temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x2b) & 0x0f;
-   temp = (USHORT)((int)(temp) + shift);
+   temp = (unsigned short)((int)(temp) + shift);
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2b,0xf0,(temp & 0x0f));
    temp1 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
    temp2 = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x42);
-   temp = (USHORT)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
+   temp = (unsigned short)((int)((temp1 | ((temp2 & 0xf0) << 4))) + shift);
    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,temp);
    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x42,0x0f,((temp >> 4) & 0xf0));
 }
+#endif
 
 static void
-SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                    USHORT ModeNo, USHORT ModeIdIndex)
+SiS_SetGroup4_C_ELV(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-   USHORT temp, temp1, resinfo = 0;
+   unsigned short temp, temp1, resinfo = 0;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 
-   if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
+   if(!(SiS_Pr->SiS_VBType & VB_SIS30xCLV)) return;
    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
 
+   if(SiS_Pr->ChipType >= XGI_20) return;
+
+   if((SiS_Pr->ChipType >= SIS_661) && (SiS_Pr->SiS_ROMNew)) {
+      if(!(ROMAddr[0x61] & 0x04)) return;
+   }
+
    if(ModeNo > 0x13) {
       resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
    }
@@ -7625,7 +7432,7 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
    if(!(temp & 0x01)) {
       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3a,0xdf);
       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xfc);
-      if((HwInfo->jChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
+      if((SiS_Pr->ChipType < SIS_661) && (!(SiS_Pr->SiS_ROMNew))) {
          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x25,0xf8);
       }
       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x0f,0xfb);
@@ -7633,24 +7440,29 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
       else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) temp = 0x0002;
       else if(SiS_Pr->SiS_TVMode & TVSetHiVision)  temp = 0x0400;
       else                                        temp = 0x0402;
-      if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
+      if((SiS_Pr->ChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
          temp1 = 0;
         if(SiS_Pr->SiS_TVMode & TVAspect43) temp1 = 4;
         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0f,0xfb,temp1);
         if(SiS_Pr->SiS_TVMode & TVAspect43LB) temp |= 0x01;
         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0x7c,(temp & 0xff));
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+        if(ModeNo > 0x13) {
+            SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x39,0xfd);
+         }
       } else {
          temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x3b) & 0x03;
         if(temp1 == 0x01) temp |= 0x01;
         if(temp1 == 0x03) temp |= 0x04;  /* ? why not 0x10? */
         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x26,0xf8,(temp & 0xff));
-      }
-      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
-      if(ModeNo > 0x13) {
-         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+        SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x3a,0xfb,(temp >> 8));
+        if(ModeNo > 0x13) {
+            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x3b,0xfd);
+         }
       }
 
-      if(HwInfo->jChipType >= SIS_661) {               /* ? */
+#if 0
+      if(SiS_Pr->ChipType >= SIS_661) {                /* ? */
          if(SiS_Pr->SiS_TVMode & TVAspect43) {
             if(SiS_Pr->SiS_TVMode & TVSetYPbPr750p) {
               if(resinfo == SIS_RI_1024x768) {
@@ -7663,29 +7475,30 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
            }
          }
       }
+#endif
+
    }
+
 }
 #endif
 
 static void
-SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                 USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2VCLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                 unsigned short RefreshRateTableIndex)
 {
-  USHORT vclkindex;
-  USHORT temp, reg1, reg2;
+  unsigned short vclkindex, temp, reg1, reg2;
 
   if(SiS_Pr->UseCustomMode) {
      reg1 = SiS_Pr->CSR2B;
      reg2 = SiS_Pr->CSR2C;
   } else {
-     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
-                                 HwInfo);
+     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
      reg1 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_A;
      reg2 = SiS_Pr->SiS_VBVCLKData[vclkindex].Part4_B;
   }
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-     if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
+     if(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSet525p1024)) {
         SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,0x57);
        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,0x46);
        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1f,0xf6);
@@ -7698,18 +7511,42 @@ SiS_SetCRT2VCLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0b,reg2);
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x0a,reg1);
   }
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
-  temp = 0x08;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
-  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x12,0x00);
+  temp = 0x08;
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) temp |= 0x20;
+  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x12,temp);
+}
+
+static void
+SiS_SetDualLinkEtc(struct SiS_Private *SiS_Pr)
+{
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBType & VB_SISDUALLINK) {
+       if((SiS_CRT2IsLCD(SiS_Pr)) ||
+          (SiS_IsVAMode(SiS_Pr))) {
+          if(SiS_Pr->SiS_LCDInfo & LCDDualLink) {
+             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
+          } else {
+             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
+          }
+       }
+     }
+  }
+  if(SiS_Pr->SiS_VBType & VB_SISEMI) {
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
+#ifdef SET_EMI
+     SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+#endif
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+  }
 }
 
 static void
-SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-             USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetGroup4(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
 {
-  USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
-  ULONG tempebx,tempeax,templong;
+  unsigned short tempax, tempcx, tempbx, modeflag, temp, resinfo;
+  unsigned int   tempebx, tempeax, templong;
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
@@ -7722,38 +7559,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
-        }
+  if(SiS_Pr->ChipType >= SIS_315H) {
+     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
+       if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
+          SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
+       }
      }
   }
 
-  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV)) {
+  if(SiS_Pr->SiS_VBType & (VB_SIS30xCLV | VB_SIS302LV)) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
+       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x10,0x9f);
      }
   }
 
-  if(HwInfo->jChipType >= SIS_315H) {
+  if(SiS_Pr->ChipType >= SIS_315H) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
-        if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-          if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
-          } else {
-             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
-          }
-
-          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-             SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
-             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
-             SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-          }
-       }
-       return;
+       SiS_SetDualLinkEtc(SiS_Pr);
+       return;
      }
   }
 
@@ -7777,16 +7600,16 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
 
   tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK)            tempbx >>= 1;
-  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+  if(modeflag & HalfDCLK)    tempbx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
      temp = 0;
      if(tempbx > 800)        temp = 0x60;
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      temp = 0;
-     if(tempbx == 1024)      temp = 0xA0;
-     else if(tempbx > 1024)  temp = 0xC0;
+     if(tempbx > 1024)       temp = 0xC0;
+     else if(tempbx >= 960)  temp = 0xA0;
   } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
      temp = 0;
      if(tempbx >= 1280)      temp = 0x40;
@@ -7796,8 +7619,13 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      if(tempbx >= 1024)      temp = 0xA0;
   }
 
+  temp |= SiS_Pr->Init_P4_0E;
+
   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) {
+        temp &= 0xf0;
+        temp |= 0x0A;
+     }
   }
 
   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
@@ -7824,15 +7652,15 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   tempeax /= tempebx;
   if(templong) tempeax++;
 
-  temp = (USHORT)(tempeax & 0x000000FF);
+  temp = (unsigned short)(tempeax & 0x000000FF);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
-  temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
+  temp = (unsigned short)((tempeax & 0x0000FF00) >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
-  temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
+  temp = (unsigned short)((tempeax >> 12) & 0x70); /* sic! */
   temp |= (tempcx & 0x4F);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
 
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
 
@@ -7840,23 +7668,26 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      tempbx = 0;
      if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
      tempax = SiS_Pr->SiS_VGAHDE;
-     if(modeflag & HalfDCLK)            tempax >>= 1;
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
+     if(modeflag & HalfDCLK)    tempax >>= 1;
+     if(SiS_IsDualLink(SiS_Pr)) tempax >>= 1;
      if(tempax > 800) {
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
           tempax -= 800;
-       } else {  /* 651+301C: Only if TVNoHiviNoYPbPr */
+       } else {
           tempbx = 0x08;
-           if(tempax == 1024) tempax *= 25;
-           else                      tempax *= 20;
+          if(tempax == 960)       tempax *= 25; /* Correct */
+           else if(tempax == 1024) tempax *= 25;
+           else                           tempax *= 20;
           temp = tempax % 32;
           tempax /= 32;
           if(temp) tempax++;
           tempax++;
-          if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) ||
-             (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
-             if(resinfo == SIS_RI_1024x768) {
-                /* Otherwise white line at right edge */
+          if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+             if(resinfo == SIS_RI_1024x768 ||
+                resinfo == SIS_RI_1024x576 ||
+                resinfo == SIS_RI_1280x1024 ||
+                resinfo == SIS_RI_1280x720) {
+                /* Otherwise white line or garbage at right edge */
                 tempax = (tempax & 0xff00) | 0x20;
              }
           }
@@ -7868,7 +7699,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
 
      temp = 0x0036; tempbx = 0xD0;
-     if((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+     if((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
        temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
      }
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -7884,36 +7715,24 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
 
      tempbx = SiS_Pr->SiS_HT >> 1;
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+     if(SiS_IsDualLink(SiS_Pr)) tempbx >>= 1;
      tempbx -= 2;
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
      temp = (tempbx >> 5) & 0x38;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+     if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
            SiS_SetReg(SiS_Pr->SiS_Part4Port,0x24,0x0e);
           /* LCD-too-dark-error-source, see FinalizeLCD() */
        }
-       if(HwInfo->jChipType >= SIS_315H) {
-          if(SiS_IsDualLink(SiS_Pr, HwInfo)) {
-             SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x2c);
-          } else {
-             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x27,~0x20);
-          }
-       }
-       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-          SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
-#ifdef SET_EMI
-          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-#endif
-          SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-       }
      }
 
+     SiS_SetDualLinkEtc(SiS_Pr);
+
   }  /* 301B */
 
-  SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+  SiS_SetCRT2VCLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 }
 
 /*********************************************/
@@ -7921,8 +7740,7 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-              PSIS_HW_INFO HwInfo)
+SiS_SetGroup5(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)  return;
@@ -7930,7 +7748,7 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   if(SiS_Pr->SiS_ModeType == ModeVGA) {
      if(!(SiS_Pr->SiS_VBInfo & (SetInSlaveMode | LoadDACFlag))) {
         SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-        SiS_LoadDAC(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+        SiS_LoadDAC(SiS_Pr, ModeNo, ModeIdIndex);
      }
   }
 }
@@ -7939,116 +7757,156 @@ SiS_SetGroup5(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*     MODIFY CRT1 GROUP FOR SLAVE MODE      */
 /*********************************************/
 
-static void
-SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
-{
-  USHORT tempah,i,modeflag,j;
-  USHORT ResIndex,DisplayType;
-  const SiS_LVDSCRT1DataStruct *LVDSCRT1Ptr=NULL;
+static BOOLEAN
+SiS_GetLVDSCRT1Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                  unsigned short RefreshRateTableIndex, unsigned short *ResIndex,
+                  unsigned short *DisplayType)
+ {
+  unsigned short modeflag = 0;
+  BOOLEAN checkhd = TRUE;
+
+  /* Pass 1:1 not supported here */
+
+  if(ModeNo <= 0x13) {
+     modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     (*ResIndex) = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+  } else {
+     modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+     (*ResIndex) = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+  }
+
+  (*ResIndex) &= 0x3F;
+
+  if((SiS_Pr->SiS_IF_DEF_CH70xx) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
+
+     (*DisplayType) = 80;
+     if((SiS_Pr->SiS_TVMode & TVSetPAL) && (!(SiS_Pr->SiS_TVMode & TVSetPALM))) {
+       (*DisplayType) = 82;
+       if(SiS_Pr->SiS_ModeType > ModeVGA) {
+          if(SiS_Pr->SiS_CHSOverScan) (*DisplayType) = 84;
+       }
+     }
+     if((*DisplayType) != 84) {
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) (*DisplayType)++;
+     }
+
+  } else {
+
+     (*DisplayType = 0);
+     switch(SiS_Pr->SiS_LCDResInfo) {
+     case Panel_320x240_1: (*DisplayType) = 50;
+                          checkhd = FALSE;
+                          break;
+     case Panel_320x240_2: (*DisplayType) = 14;
+                          break;
+     case Panel_320x240_3: (*DisplayType) = 18;
+                          break;
+     case Panel_640x480:   (*DisplayType) = 10;
+                          break;
+     case Panel_1024x600:  (*DisplayType) = 26;
+                          break;
+     default: return TRUE;
+     }
+
+     if(checkhd) {
+        if(modeflag & HalfDCLK) (*DisplayType)++;
+     }
+
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x600) {
+        if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) (*DisplayType) += 2;
+     }
+
+  }
+
+  return TRUE;
+}
 
-  if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+static void
+SiS_ModCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                unsigned short RefreshRateTableIndex)
+{
+  unsigned short tempah, i, modeflag, j, ResIndex, DisplayType;
+  const struct SiS_LVDSCRT1Data *LVDSCRT1Ptr=NULL;
+  static const unsigned short CRIdx[] = {
+       0x00, 0x02, 0x03, 0x04, 0x05, 0x06,
+       0x07, 0x10, 0x11, 0x15, 0x16
+  };
 
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
      (SiS_Pr->SiS_CustomT == CUT_BARCO1024) ||
-     (SiS_Pr->SiS_CustomT == CUT_PANEL848))
+     (SiS_Pr->SiS_CustomT == CUT_PANEL848)  ||
+     (SiS_Pr->SiS_CustomT == CUT_PANEL856) )
      return;
 
+  if(SiS_Pr->SiS_IF_DEF_LVDS) {
+     if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
+        if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+     }
+  } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) return;
+  } else return;
+
+  if(SiS_Pr->SiS_LCDInfo & LCDPass11) return;
+
+  if(SiS_Pr->ChipType < SIS_315H) {
+     if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+  }
+
   if(!(SiS_GetLVDSCRT1Ptr(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex,
                           &ResIndex, &DisplayType))) {
      return;
   }
 
-  if(HwInfo->jChipType < SIS_315H) {
-     if(SiS_Pr->SiS_SetFlag & SetDOSMode) return;
+  switch(DisplayType) {
+    case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_1;           break; /* xSTN */
+    case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2;           break; /* xSTN */
+    case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_2_H;         break; /* xSTN */
+    case 18: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3;           break; /* xSTN */
+    case 19: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x240_3_H;         break; /* xSTN */
+    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
+    case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
+#if 0 /* Works better with calculated numbers */
+    case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
+    case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
+    case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
+    case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
+#endif
+    case 80: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
+    case 81: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
+    case 82: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
+    case 83: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
+    case 84: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
   }
 
-  switch(DisplayType) {
-    case 0 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1;           break;
-    case 1 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_1_H;         break;
-    case 2 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2;           break;
-    case 3 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1800x600_2_H;         break;
-    case 4 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
-    case 5 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1_H;        break;
-    case 6 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2;          break;
-    case 7 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_2_H;        break;
-    case 8 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1;         break;
-    case 9 : LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_1_H;       break;
-    case 10: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2;         break;
-    case 11: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x1024_2_H;       break;
-    case 12: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1;           break;
-    case 13: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1XXXxXXX_1_H;         break;
-    case 14: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1;         break;
-    case 15: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_1_H;       break;
-    case 16: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2;         break;
-    case 17: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11400x1050_2_H;       break;
-    case 18: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UNTSC;               break;
-    case 19: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1ONTSC;               break;
-    case 20: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1UPAL;                break;
-    case 21: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1OPAL;                break;
-    case 22: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1320x480_1;           break; /* FSTN */
-    case 23: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1;          break;
-    case 24: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_1_H;        break;
-    case 25: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2;          break;
-    case 26: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x600_2_H;        break;
-    case 27: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1;          break;
-    case 28: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_1_H;        break;
-    case 29: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2;          break;
-    case 30: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11152x768_2_H;        break;
-    case 36: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1;         break;
-    case 37: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_1_H;       break;
-    case 38: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2;         break;
-    case 39: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11600x1200_2_H;       break;
-    case 40: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1;          break;
-    case 41: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_1_H;        break;
-    case 42: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2;          break;
-    case 43: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11280x768_2_H;        break;
-    case 50: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1;           break;
-    case 51: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_1_H;         break;
-    case 52: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2;           break;
-    case 53: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_2_H;         break;
-    case 54: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3;           break;
-    case 55: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT1640x480_3_H;         break;
-    case 99: LVDSCRT1Ptr = SiS_Pr->SiS_CHTVCRT1SOPAL;               break;
-    default: LVDSCRT1Ptr = SiS_Pr->SiS_LVDSCRT11024x768_1;          break;
-  }
-
-  SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
-
-  tempah = (LVDSCRT1Ptr + ResIndex)->CR[0];
-  SiS_SetReg(SiS_Pr->SiS_P3d4,0x00,tempah);
-
-  for(i=0x02,j=1;i<=0x05;i++,j++){
-    tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
-    SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
-  }
-  for(i=0x06,j=5;i<=0x07;i++,j++){
-    tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
-    SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
-  }
-  for(i=0x10,j=7;i<=0x11;i++,j++){
-    tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
-    SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
-  }
-  for(i=0x15,j=9;i<=0x16;i++,j++){
-    tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
-    SiS_SetReg(SiS_Pr->SiS_P3d4,i,tempah);
-  }
-  for(i=0x0A,j=11;i<=0x0C;i++,j++){
-    tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
-    SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
-  }
-
-  tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
-  tempah &= 0xE0;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
-
-  tempah = (LVDSCRT1Ptr + ResIndex)->CR[14];
-  tempah &= 0x01;
-  tempah <<= 5;
-  if(modeflag & DoubleScanMode)  tempah |= 0x080;
-  SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+  if(LVDSCRT1Ptr) {
+
+     SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x11,0x7f);
+
+     for(i = 0; i <= 10; i++) {
+        tempah = (LVDSCRT1Ptr + ResIndex)->CR[i];
+        SiS_SetReg(SiS_Pr->SiS_P3d4,CRIdx[i],tempah);
+     }
+
+     for(i = 0x0A, j = 11; i <= 0x0C; i++, j++) {
+        tempah = (LVDSCRT1Ptr + ResIndex)->CR[j];
+        SiS_SetReg(SiS_Pr->SiS_P3c4,i,tempah);
+     }
+
+     tempah = (LVDSCRT1Ptr + ResIndex)->CR[14] & 0xE0;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x0E,0x1f,tempah);
+
+     if(ModeNo <= 0x13) modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
+     else               modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+     tempah = ((LVDSCRT1Ptr + ResIndex)->CR[14] & 0x01) << 5;
+     if(modeflag & DoubleScanMode) tempah |= 0x80;
+     SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x09,~0x020,tempah);
+
+  } else {
+
+     SiS_CalcLCDACRT1Timing(SiS_Pr, ModeNo, ModeIdIndex);
+
+  }
 }
 
 /*********************************************/
@@ -8056,24 +7914,24 @@ SiS_ModCRT1CRTC(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-           USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
+SiS_SetCRT2ECLK(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+           unsigned short RefreshRateTableIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT clkbase, vclkindex=0;
-  UCHAR  sr2b, sr2c;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short clkbase, vclkindex = 0;
+  unsigned char  sr2b, sr2c;
 
-  if((SiS_Pr->SiS_LCDResInfo == Panel_640x480) || (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-       SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
-        if((SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK & 0x3f) == 2) {
-          RefreshRateTableIndex--;
-       }
-       vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
-                                    RefreshRateTableIndex, HwInfo);
-       SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
+  if(SiS_Pr->SiS_LCDInfo & LCDPass11) {
+     SiS_Pr->SiS_SetFlag &= (~ProgrammingCRT2);
+     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRTVCLK == 2) {
+       RefreshRateTableIndex--;
+     }
+     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+                                    RefreshRateTableIndex);
+     SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
   } else {
-        vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
-                                    RefreshRateTableIndex, HwInfo);
+     vclkindex = SiS_GetVCLK2Ptr(SiS_Pr, ModeNo, ModeIdIndex,
+                                    RefreshRateTableIndex);
   }
 
   sr2b = SiS_Pr->SiS_VCLKData[vclkindex].SR2B;
@@ -8082,7 +7940,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) || (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
      if(SiS_Pr->SiS_UseROM) {
        if(ROMAddr[0x220] & 0x01) {
-           sr2b = ROMAddr[0x227];
+          sr2b = ROMAddr[0x227];
           sr2c = ROMAddr[0x228];
        }
      }
@@ -8091,7 +7949,7 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   clkbase = 0x02B;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
      if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) {
-       clkbase += 3;
+       clkbase += 3;
      }
   }
 
@@ -8111,368 +7969,331 @@ SiS_SetCRT2ECLK(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 /*********************************************/
 
 static void
-SiS_SetCHTVReg(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-               USHORT RefreshRateTableIndex)
+SiS_SetCHTVReg(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+               unsigned short RefreshRateTableIndex)
 {
-#if defined(SIS300) || defined(SIS315H)
-  USHORT temp, tempbx;
-#endif
-  USHORT tempcl;
-  USHORT TVType, resindex;
-  const SiS_CHTVRegDataStruct *CHTVRegData = NULL;
+   unsigned short TVType, resindex;
+   const struct SiS_CHTVRegData *CHTVRegData = NULL;
 
-  if(ModeNo <= 0x13)
-     tempcl = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-  else
-     tempcl = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+   if(ModeNo <= 0x13)
+      resindex = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+   else
+      resindex = SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
-  TVType = 0;
-  if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
-  if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-       TVType += 2;
-       if(SiS_Pr->SiS_ModeType > ModeVGA) {
-          if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
-       }
-       if(SiS_Pr->SiS_TVMode & TVSetPALM) {
-               TVType = 4;
-               if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
-       } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
-               TVType = 6;
-               if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
-       }
-  }
-  switch(TVType) {
-     case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
-     case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
-     case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
-     case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-     case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
-     case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
-     case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
-     case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
-     case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
-     default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
-  }
-  resindex = tempcl & 0x3F;
+   resindex &= 0x3F;
 
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
+   TVType = 0;
+   if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+   if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+      TVType += 2;
+      if(SiS_Pr->SiS_ModeType > ModeVGA) {
+        if(SiS_Pr->SiS_CHSOverScan) TVType = 8;
+      }
+      if(SiS_Pr->SiS_TVMode & TVSetPALM) {
+        TVType = 4;
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+      } else if(SiS_Pr->SiS_TVMode & TVSetPALN) {
+        TVType = 6;
+        if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) TVType += 1;
+      }
+   }
+
+   switch(TVType) {
+      case  0: CHTVRegData = SiS_Pr->SiS_CHTVReg_UNTSC; break;
+      case  1: CHTVRegData = SiS_Pr->SiS_CHTVReg_ONTSC; break;
+      case  2: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPAL;  break;
+      case  3: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+      case  4: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALM; break;
+      case  5: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALM; break;
+      case  6: CHTVRegData = SiS_Pr->SiS_CHTVReg_UPALN; break;
+      case  7: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPALN; break;
+      case  8: CHTVRegData = SiS_Pr->SiS_CHTVReg_SOPAL; break;
+      default: CHTVRegData = SiS_Pr->SiS_CHTVReg_OPAL;  break;
+   }
+
+
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
 
 #ifdef SIS300
 
-     /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
+      /* Chrontel 7005 - I assume that it does not come with a 315 series chip */
 
-     /* We don't support modes >800x600 */
-     if (resindex > 5) return;
+      /* We don't support modes >800x600 */
+      if (resindex > 5) return;
 
-     if(SiS_Pr->SiS_TVMode & TVSetPAL) {
-       SiS_SetCH700x(SiS_Pr,0x4304);   /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
-       SiS_SetCH700x(SiS_Pr,0x6909);   /* Black level for PAL (105)*/
-     } else {
-       SiS_SetCH700x(SiS_Pr,0x0304);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
-       SiS_SetCH700x(SiS_Pr,0x7109);   /* Black level for NTSC (113)*/
-     }
-
-     temp = CHTVRegData[resindex].Reg[0];
-     tempbx=((temp&0x00FF)<<8)|0x00;   /* Mode register */
-     SiS_SetCH700x(SiS_Pr,tempbx);
-     temp = CHTVRegData[resindex].Reg[1];
-     tempbx=((temp&0x00FF)<<8)|0x07;   /* Start active video register */
-     SiS_SetCH700x(SiS_Pr,tempbx);
-     temp = CHTVRegData[resindex].Reg[2];
-     tempbx=((temp&0x00FF)<<8)|0x08;   /* Position overflow register */
-     SiS_SetCH700x(SiS_Pr,tempbx);
-     temp = CHTVRegData[resindex].Reg[3];
-     tempbx=((temp&0x00FF)<<8)|0x0A;   /* Horiz Position register */
-     SiS_SetCH700x(SiS_Pr,tempbx);
-     temp = CHTVRegData[resindex].Reg[4];
-     tempbx=((temp&0x00FF)<<8)|0x0B;   /* Vertical Position register */
-     SiS_SetCH700x(SiS_Pr,tempbx);
-
-     /* Set minimum flicker filter for Luma channel (SR1-0=00),
+      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
+        SiS_SetCH700x(SiS_Pr,0x04,0x43);  /* 0x40=76uA (PAL); 0x03=15bit non-multi RGB*/
+        SiS_SetCH700x(SiS_Pr,0x09,0x69);  /* Black level for PAL (105)*/
+      } else {
+        SiS_SetCH700x(SiS_Pr,0x04,0x03);   /* upper nibble=71uA (NTSC), 0x03=15bit non-multi RGB*/
+        SiS_SetCH700x(SiS_Pr,0x09,0x71);   /* Black level for NTSC (113)*/
+      }
+
+      SiS_SetCH700x(SiS_Pr,0x00,CHTVRegData[resindex].Reg[0]); /* Mode register */
+      SiS_SetCH700x(SiS_Pr,0x07,CHTVRegData[resindex].Reg[1]); /* Start active video register */
+      SiS_SetCH700x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[2]); /* Position overflow register */
+      SiS_SetCH700x(SiS_Pr,0x0a,CHTVRegData[resindex].Reg[3]); /* Horiz Position register */
+      SiS_SetCH700x(SiS_Pr,0x0b,CHTVRegData[resindex].Reg[4]); /* Vertical Position register */
+
+      /* Set minimum flicker filter for Luma channel (SR1-0=00),
                 minimum text enhancement (S3-2=10),
                maximum flicker filter for Chroma channel (S5-4=10)
                =00101000=0x28 (When reading, S1-0->S3-2, and S3-2->S1-0!)
-      */
-     SiS_SetCH700x(SiS_Pr,0x2801);
+       */
+      SiS_SetCH700x(SiS_Pr,0x01,0x28);
 
-     /* Set video bandwidth
+      /* Set video bandwidth
             High bandwith Luma composite video filter(S0=1)
             low bandwith Luma S-video filter (S2-1=00)
            disable peak filter in S-video channel (S3=0)
            high bandwidth Chroma Filter (S5-4=11)
            =00110001=0x31
-     */
-     SiS_SetCH700x(SiS_Pr,0xb103);       /* old: 3103 */
+      */
+      SiS_SetCH700x(SiS_Pr,0x03,0xb1);       /* old: 3103 */
 
-     /* Register 0x3D does not exist in non-macrovision register map
+      /* Register 0x3D does not exist in non-macrovision register map
             (Maybe this is a macrovision register?)
-      */
+       */
 #ifndef SIS_CP
-     SiS_SetCH70xx(SiS_Pr,0x003D);
+      SiS_SetCH70xx(SiS_Pr,0x3d,0x00);
 #endif
 
-     /* Register 0x10 only contains 1 writable bit (S0) for sensing,
-            all other bits a read-only. Macrovision?
-      */
-     SiS_SetCH70xxANDOR(SiS_Pr,0x0010,0x1F);
+      /* Register 0x10 only contains 1 writable bit (S0) for sensing,
+             all other bits a read-only. Macrovision?
+       */
+      SiS_SetCH70xxANDOR(SiS_Pr,0x10,0x00,0x1F);
 
-     /* Register 0x11 only contains 3 writable bits (S0-S2) for
-            contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
-      */
-     SiS_SetCH70xxANDOR(SiS_Pr,0x0211,0xF8);
+      /* Register 0x11 only contains 3 writable bits (S0-S2) for
+             contrast enhancement (set to 010 -> gain 1 Yout = 17/16*(Yin-30) )
+       */
+      SiS_SetCH70xxANDOR(SiS_Pr,0x11,0x02,0xF8);
 
-     /* Clear DSEN
-      */
-     SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xEF);
-
-     if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {            /* ---- NTSC ---- */
-       if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
-         if(resindex == 0x04) {                        /* 640x480 overscan: Mode 16 */
-          SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on, no need to set FSCI */
-         } else if(resindex == 0x05) {                 /* 800x600 overscan: Mode 23 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0);     /* 0x18-0x1f: FSCI 469,762,048 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0C19,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x001A,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x001B,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x001C,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x001D,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x001E,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x001F,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0120,0xEF);       /* Loop filter on for mode 23 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE);       /* ACIV off, need to set FSCI */
-         }
-       } else {
-         if(resindex == 0x04) {                         /* ----- 640x480 underscan; Mode 17 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);      /* loop filter off */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
-         } else if(resindex == 0x05) {                  /* ----- 800x600 underscan: Mode 24 */
+      /* Clear DSEN
+       */
+      SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xEF);
+
+      if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {           /* ---- NTSC ---- */
+         if(SiS_Pr->SiS_TVMode & TVSetCHOverScan) {
+            if(resindex == 0x04) {                     /* 640x480 overscan: Mode 16 */
+              SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);       /* loop filter off */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);      /* ACIV on, no need to set FSCI */
+            } else if(resindex == 0x05) {              /* 800x600 overscan: Mode 23 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);      /* 0x18-0x1f: FSCI 469,762,048 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x0C,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x00,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x01,0xEF);      /* Loop filter on for mode 23 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);      /* ACIV off, need to set FSCI */
+            }
+         } else {
+            if(resindex == 0x04) {                             /* ----- 640x480 underscan; Mode 17 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);      /* loop filter off */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+            } else if(resindex == 0x05) {              /* ----- 800x600 underscan: Mode 24 */
 #if 0
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0118,0xF0);       /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0919,0xF0);      /* FSCI for mode 24 is 428,554,851 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x081A,0xF0);       /* 198b3a63 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0b1B,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x041C,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x011D,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x061E,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x051F,0xF0);
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off for mode 24 */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0021,0xFE);      /* ACIV off, need to set FSCI */
-#endif     /* All alternatives wrong (datasheet wrong?), don't use FSCI */
-          SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);       /* loop filter off */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x18,0x01,0xF0);      /* (FSCI was 0x1f1c71c7 - this is for mode 22) */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x19,0x09,0xF0);      /* FSCI for mode 24 is 428,554,851 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1a,0x08,0xF0);       /* 198b3a63 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1b,0x0b,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1c,0x04,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1d,0x01,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1e,0x06,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x1f,0x05,0xF0);
+               SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);      /* loop filter off for mode 24 */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x00,0xFE);      * ACIV off, need to set FSCI */
+#endif         /* All alternatives wrong (datasheet wrong?), don't use FSCI */
+              SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF);        /* loop filter off */
+               SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE);
+            }
          }
-       }
-     } else {                                          /* ---- PAL ---- */
-           /* We don't play around with FSCI in PAL mode */
+      } else {                                         /* ---- PAL ---- */
+         /* We don't play around with FSCI in PAL mode */
          if(resindex == 0x04) {
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);     /* loop filter off */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on */
+            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
          } else {
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0020,0xEF);     /* loop filter off */
-           SiS_SetCH70xxANDOR(SiS_Pr,0x0121,0xFE);      /* ACIV on */
+            SiS_SetCH70xxANDOR(SiS_Pr,0x20,0x00,0xEF); /* loop filter off */
+            SiS_SetCH70xxANDOR(SiS_Pr,0x21,0x01,0xFE); /* ACIV on */
          }
-     }
-     
+      }
+
 #endif  /* 300 */
 
-  } else {
+   } else {
 
-     /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
+      /* Chrontel 7019 - assumed that it does not come with a 300 series chip */
 
 #ifdef SIS315H
 
-     /* We don't support modes >1024x768 */
-     if (resindex > 6) return;
-
-     temp = CHTVRegData[resindex].Reg[0];
-     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-        temp |= 0x10;
-     }
-     tempbx=((temp & 0x00FF) << 8) | 0x00;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[1];
-     tempbx=((temp & 0x00FF) << 8) | 0x01;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[2];
-     tempbx=((temp & 0x00FF) << 8) | 0x02;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[3];
-     tempbx=((temp & 0x00FF) << 8) | 0x04;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[4];
-     tempbx=((temp & 0x00FF) << 8) | 0x03;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[5];
-     tempbx=((temp & 0x00FF) << 8) | 0x05;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[6];
-     tempbx=((temp & 0x00FF) << 8) | 0x06;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[7];
-     if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) {
-       temp = 0x66;
-     }
-     tempbx=((temp & 0x00FF) << 8) | 0x07;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[8];
-     tempbx=((temp & 0x00FF) << 8) | 0x08;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[9];
-     tempbx=((temp & 0x00FF) << 8) | 0x15;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[10];
-     tempbx=((temp & 0x00FF) << 8) | 0x1f;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[11];
-     tempbx=((temp & 0x00FF) << 8) | 0x0c;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[12];
-     tempbx=((temp & 0x00FF) << 8) | 0x0d;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[13];
-     tempbx=((temp & 0x00FF) << 8) | 0x0e;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[14];
-     tempbx=((temp & 0x00FF) << 8) | 0x0f;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = CHTVRegData[resindex].Reg[15];
-     tempbx=((temp & 0x00FF) << 8) | 0x10;
-     SiS_SetCH701x(SiS_Pr,tempbx);
-
-     temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
-     /* D1 should be set for PAL, PAL-N and NTSC-J,
-        but I won't do that for PAL unless somebody
-       tells me to do so. Since the BIOS uses
-       non-default CIV values and blacklevels,
-       this might be compensated anyway.
-      */
-     if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
-     SiS_SetCH701x(SiS_Pr,((temp << 8) | 0x21));
+      unsigned short temp;
+
+      /* We don't support modes >1024x768 */
+      if (resindex > 6) return;
+
+      temp = CHTVRegData[resindex].Reg[0];
+      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp |= 0x10;
+      SiS_SetCH701x(SiS_Pr,0x00,temp);
+
+      SiS_SetCH701x(SiS_Pr,0x01,CHTVRegData[resindex].Reg[1]);
+      SiS_SetCH701x(SiS_Pr,0x02,CHTVRegData[resindex].Reg[2]);
+      SiS_SetCH701x(SiS_Pr,0x04,CHTVRegData[resindex].Reg[3]);
+      SiS_SetCH701x(SiS_Pr,0x03,CHTVRegData[resindex].Reg[4]);
+      SiS_SetCH701x(SiS_Pr,0x05,CHTVRegData[resindex].Reg[5]);
+      SiS_SetCH701x(SiS_Pr,0x06,CHTVRegData[resindex].Reg[6]);
+
+      temp = CHTVRegData[resindex].Reg[7];
+      if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) temp = 0x66;
+      SiS_SetCH701x(SiS_Pr,0x07,temp);
+
+      SiS_SetCH701x(SiS_Pr,0x08,CHTVRegData[resindex].Reg[8]);
+      SiS_SetCH701x(SiS_Pr,0x15,CHTVRegData[resindex].Reg[9]);
+      SiS_SetCH701x(SiS_Pr,0x1f,CHTVRegData[resindex].Reg[10]);
+      SiS_SetCH701x(SiS_Pr,0x0c,CHTVRegData[resindex].Reg[11]);
+      SiS_SetCH701x(SiS_Pr,0x0d,CHTVRegData[resindex].Reg[12]);
+      SiS_SetCH701x(SiS_Pr,0x0e,CHTVRegData[resindex].Reg[13]);
+      SiS_SetCH701x(SiS_Pr,0x0f,CHTVRegData[resindex].Reg[14]);
+      SiS_SetCH701x(SiS_Pr,0x10,CHTVRegData[resindex].Reg[15]);
+
+      temp = SiS_GetCH701x(SiS_Pr,0x21) & ~0x02;
+      /* D1 should be set for PAL, PAL-N and NTSC-J,
+         but I won't do that for PAL unless somebody
+        tells me to do so. Since the BIOS uses
+        non-default CIV values and blacklevels,
+        this might be compensated anyway.
+       */
+      if(SiS_Pr->SiS_TVMode & (TVSetPALN | TVSetNTSCJ)) temp |= 0x02;
+      SiS_SetCH701x(SiS_Pr,0x21,temp);
 
 #endif /* 315 */
 
-  }
+   }
 
 #ifdef SIS_CP
-  SIS_CP_INIT301_CP3
+   SIS_CP_INIT301_CP3
 #endif
 
 }
 
+#ifdef SIS315H  /* ----------- 315 series only ---------- */
+
 void
-SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr)
 {
-  USHORT temp;
+   unsigned short temp;
 
-  /* Enable Chrontel 7019 LCD panel backlight */
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-     if(HwInfo->jChipType == SIS_740) {
-        SiS_SetCH701x(SiS_Pr,0x6566);
-     } else {
-        temp = SiS_GetCH701x(SiS_Pr,0x66);
-        temp |= 0x20;
-       SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
-     }
-  }
+   /* Enable Chrontel 7019 LCD panel backlight */
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+      if(SiS_Pr->ChipType == SIS_740) {
+        SiS_SetCH701x(SiS_Pr,0x66,0x65);
+      } else {
+        temp = SiS_GetCH701x(SiS_Pr,0x66);
+        temp |= 0x20;
+        SiS_SetCH701x(SiS_Pr,0x66,temp);
+      }
+   }
 }
 
 void
-SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr)
+SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr)
 {
-  USHORT temp;
+   unsigned short temp;
 
-  /* Disable Chrontel 7019 LCD panel backlight */
-  if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-     temp = SiS_GetCH701x(SiS_Pr,0x66);
-     temp &= 0xDF;
-     SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
-  }
+   /* Disable Chrontel 7019 LCD panel backlight */
+   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+      temp = SiS_GetCH701x(SiS_Pr,0x66);
+      temp &= 0xDF;
+      SiS_SetCH701x(SiS_Pr,0x66,temp);
+   }
 }
 
-#ifdef SIS315H  /* ----------- 315 series only ---------- */
-
 static void
-SiS_ChrontelPowerSequencing(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
-  UCHAR regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
-  UCHAR table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
-  UCHAR table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
-  UCHAR asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
-  UCHAR asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
-  UCHAR table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
-  UCHAR table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
-  UCHAR *tableptr = NULL;
+SiS_ChrontelPowerSequencing(struct SiS_Private *SiS_Pr)
+{
+  static const unsigned char regtable[]      = { 0x67, 0x68, 0x69, 0x6a, 0x6b };
+  static const unsigned char table1024_740[] = { 0x01, 0x02, 0x01, 0x01, 0x01 };
+  static const unsigned char table1400_740[] = { 0x01, 0x6e, 0x01, 0x01, 0x01 };
+  static const unsigned char asus1024_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+  static const unsigned char asus1400_740[]  = { 0x19, 0x6e, 0x01, 0x19, 0x09 };
+  static const unsigned char table1024_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+  static const unsigned char table1400_650[] = { 0x01, 0x02, 0x01, 0x01, 0x02 };
+  const unsigned char *tableptr = NULL;
   int i;
 
   /* Set up Power up/down timing */
 
-  if(HwInfo->jChipType == SIS_740) {
+  if(SiS_Pr->ChipType == SIS_740) {
      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
-        else                                     tableptr = table1024_740;
+       if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1024_740;
+       else                                      tableptr = table1024_740;
      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+              (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) tableptr = asus1400_740;
         else                                     tableptr = table1400_740;
      } else return;
   } else {
      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-        tableptr = table1024_650;
+       tableptr = table1024_650;
      } else if((SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) ||
-               (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
+              (SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
               (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200)) {
-        tableptr = table1400_650;
+       tableptr = table1400_650;
      } else return;
   }
 
   for(i=0; i<5; i++) {
-     SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
   }
 }
 
 static void
-SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
-  UCHAR regtable[]      = { 0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
-                            0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66 };
-  UCHAR table1024_740[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
-                            0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44 };
-  UCHAR table1280_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
-                           0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
-  UCHAR table1400_740[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
-                            0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44 };
-  UCHAR table1600_740[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
-                           0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44 };
-  UCHAR table1024_650[] = { 0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
-                            0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02 };
-  UCHAR table1280_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
-                           0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02 };
-  UCHAR table1400_650[] = { 0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
-                            0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02 };
-  UCHAR table1600_650[] = { 0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
-                           0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a };
-  UCHAR *tableptr = NULL;
-  USHORT tempbh;
+SiS_SetCH701xForLCD(struct SiS_Private *SiS_Pr)
+{
+  const unsigned char *tableptr = NULL;
+  unsigned short tempbh;
   int i;
+  static const unsigned char regtable[] = {
+               0x1c, 0x5f, 0x64, 0x6f, 0x70, 0x71,
+               0x72, 0x73, 0x74, 0x76, 0x78, 0x7d, 0x66
+  };
+  static const unsigned char table1024_740[] = {
+               0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+               0xa3, 0xc8, 0xc7, 0xac, 0xe0, 0x02, 0x44
+  };
+  static const unsigned char table1280_740[] = {
+               0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+               0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+  };
+  static const unsigned char table1400_740[] = {
+               0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+               0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02, 0x44
+  };
+  static const unsigned char table1600_740[] = {
+               0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+               0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a, 0x44
+  };
+  static const unsigned char table1024_650[] = {
+               0x60, 0x02, 0x00, 0x07, 0x40, 0xed,
+               0xa3, 0xc8, 0xc7, 0xac, 0x60, 0x02
+  };
+  static const unsigned char table1280_650[] = {
+               0x60, 0x03, 0x11, 0x00, 0x40, 0xe3,
+               0xad, 0xdb, 0xf6, 0xac, 0xe0, 0x02
+  };
+  static const unsigned char table1400_650[] = {
+               0x60, 0x03, 0x11, 0x00, 0x40, 0xef,
+               0xad, 0xdb, 0xf6, 0xac, 0x60, 0x02
+  };
+  static const unsigned char table1600_650[] = {
+               0x60, 0x04, 0x11, 0x00, 0x40, 0xe3,
+               0xad, 0xde, 0xf6, 0xac, 0x60, 0x1a
+  };
 
-  if(HwInfo->jChipType == SIS_740) {
+  if(SiS_Pr->ChipType == SIS_740) {
      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)       tableptr = table1024_740;
      else if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) tableptr = table1280_740;
      else if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) tableptr = table1400_740;
@@ -8499,138 +8320,139 @@ SiS_SetCH701xForLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
      }
   }
 
-  if(HwInfo->jChipType == SIS_740) tempbh = 0x0d;
-  else                            tempbh = 0x0c;
+  if(SiS_Pr->ChipType == SIS_740) tempbh = 0x0d;
+  else                           tempbh = 0x0c;
 
   for(i = 0; i < tempbh; i++) {
-     SiS_SetCH701x(SiS_Pr,(tableptr[i] << 8) | regtable[i]);
+     SiS_SetCH701x(SiS_Pr, regtable[i], tableptr[i]);
   }
-  SiS_ChrontelPowerSequencing(SiS_Pr,HwInfo);
+  SiS_ChrontelPowerSequencing(SiS_Pr);
   tempbh = SiS_GetCH701x(SiS_Pr,0x1e);
   tempbh |= 0xc0;
-  SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1e);
+  SiS_SetCH701x(SiS_Pr,0x1e,tempbh);
 
-  if(HwInfo->jChipType == SIS_740) {
+  if(SiS_Pr->ChipType == SIS_740) {
      tempbh = SiS_GetCH701x(SiS_Pr,0x1c);
      tempbh &= 0xfb;
-     SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x1c);
+     SiS_SetCH701x(SiS_Pr,0x1c,tempbh);
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
      tempbh = SiS_GetCH701x(SiS_Pr,0x64);
      tempbh |= 0x40;
-     SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x64);
+     SiS_SetCH701x(SiS_Pr,0x64,tempbh);
      tempbh = SiS_GetCH701x(SiS_Pr,0x03);
      tempbh &= 0x3f;
-     SiS_SetCH701x(SiS_Pr,(tempbh << 8) | 0x03);
+     SiS_SetCH701x(SiS_Pr,0x03,tempbh);
   }
 }
 
 static void
-SiS_ChrontelResetVSync(SiS_Private *SiS_Pr)
+SiS_ChrontelResetVSync(struct SiS_Private *SiS_Pr)
 {
   unsigned char temp, temp1;
 
   temp1 = SiS_GetCH701x(SiS_Pr,0x49);
-  SiS_SetCH701x(SiS_Pr,0x3e49);
+  SiS_SetCH701x(SiS_Pr,0x49,0x3e);
   temp = SiS_GetCH701x(SiS_Pr,0x47);
   temp &= 0x7f;        /* Use external VSYNC */
-  SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
-  SiS_LongDelay(SiS_Pr,3);
+  SiS_SetCH701x(SiS_Pr,0x47,temp);
+  SiS_LongDelay(SiS_Pr, 3);
   temp = SiS_GetCH701x(SiS_Pr,0x47);
   temp |= 0x80;        /* Use internal VSYNC */
-  SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
-  SiS_SetCH701x(SiS_Pr,(temp1 << 8) | 0x49);
+  SiS_SetCH701x(SiS_Pr,0x47,temp);
+  SiS_SetCH701x(SiS_Pr,0x49,temp1);
 }
 
 static void
-SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr)
 {
-  USHORT temp;
+  unsigned short temp;
 
   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-     if(HwInfo->jChipType == SIS_740) {
+     if(SiS_Pr->ChipType == SIS_740) {
         temp = SiS_GetCH701x(SiS_Pr,0x1c);
         temp |= 0x04;  /* Invert XCLK phase */
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+        SiS_SetCH701x(SiS_Pr,0x1c,temp);
      }
-     if(SiS_IsYPbPr(SiS_Pr, HwInfo)) {
+     if(SiS_IsYPbPr(SiS_Pr)) {
         temp = SiS_GetCH701x(SiS_Pr,0x01);
        temp &= 0x3f;
        temp |= 0x80;   /* Enable YPrPb (HDTV) */
-       SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+       SiS_SetCH701x(SiS_Pr,0x01,temp);
      }
-     if(SiS_IsChScart(SiS_Pr, HwInfo)) {
+     if(SiS_IsChScart(SiS_Pr)) {
         temp = SiS_GetCH701x(SiS_Pr,0x01);
        temp &= 0x3f;
        temp |= 0xc0;   /* Enable SCART + CVBS */
-       SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x01);
+       SiS_SetCH701x(SiS_Pr,0x01,temp);
      }
-     if(HwInfo->jChipType == SIS_740) {
+     if(SiS_Pr->ChipType == SIS_740) {
         SiS_ChrontelResetVSync(SiS_Pr);
-        SiS_SetCH701x(SiS_Pr,0x2049);   /* Enable TV path */
+        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
      } else {
-        SiS_SetCH701x(SiS_Pr,0x2049);   /* Enable TV path */
+        SiS_SetCH701x(SiS_Pr,0x49,0x20);   /* Enable TV path */
         temp = SiS_GetCH701x(SiS_Pr,0x49);
-        if(SiS_IsYPbPr(SiS_Pr,HwInfo)) {
+        if(SiS_IsYPbPr(SiS_Pr)) {
            temp = SiS_GetCH701x(SiS_Pr,0x73);
           temp |= 0x60;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x73);
+          SiS_SetCH701x(SiS_Pr,0x73,temp);
         }
         temp = SiS_GetCH701x(SiS_Pr,0x47);
         temp &= 0x7f;
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
-        SiS_LongDelay(SiS_Pr,2);
+        SiS_SetCH701x(SiS_Pr,0x47,temp);
+        SiS_LongDelay(SiS_Pr, 2);
         temp = SiS_GetCH701x(SiS_Pr,0x47);
         temp |= 0x80;
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);
+        SiS_SetCH701x(SiS_Pr,0x47,temp);
      }
   }
 }
 
 static void
-SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr)
 {
-  USHORT temp;
+  unsigned short temp;
 
   /* Complete power down of LVDS */
   if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
-     if(HwInfo->jChipType == SIS_740) {
-        SiS_LongDelay(SiS_Pr,1);
-       SiS_GenericDelay(SiS_Pr,0x16ff);
-       SiS_SetCH701x(SiS_Pr,0xac76);
-       SiS_SetCH701x(SiS_Pr,0x0066);
+     if(SiS_Pr->ChipType == SIS_740) {
+        SiS_LongDelay(SiS_Pr, 1);
+       SiS_GenericDelay(SiS_Pr, 5887);
+       SiS_SetCH701x(SiS_Pr,0x76,0xac);
+       SiS_SetCH701x(SiS_Pr,0x66,0x00);
      } else {
-        SiS_LongDelay(SiS_Pr,2);
+        SiS_LongDelay(SiS_Pr, 2);
        temp = SiS_GetCH701x(SiS_Pr,0x76);
        temp &= 0xfc;
-       SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
-       SiS_SetCH701x(SiS_Pr,0x0066);
+       SiS_SetCH701x(SiS_Pr,0x76,temp);
+       SiS_SetCH701x(SiS_Pr,0x66,0x00);
      }
   }
 }
 
 static void
-SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelResetDB(struct SiS_Private *SiS_Pr)
 {
-     USHORT temp;
+     unsigned short temp;
 
-     if(HwInfo->jChipType == SIS_740) {
+     if(SiS_Pr->ChipType == SIS_740) {
 
         temp = SiS_GetCH701x(SiS_Pr,0x4a);  /* Version ID */
         temp &= 0x01;
         if(!temp) {
 
-           if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
+           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
              temp = SiS_GetCH701x(SiS_Pr,0x49);
-             SiS_SetCH701x(SiS_Pr,0x3e49);
+             SiS_SetCH701x(SiS_Pr,0x49,0x3e);
           }
+
           /* Reset Chrontel 7019 datapath */
-           SiS_SetCH701x(SiS_Pr,0x1048);
-           SiS_LongDelay(SiS_Pr,1);
-           SiS_SetCH701x(SiS_Pr,0x1848);
+           SiS_SetCH701x(SiS_Pr,0x48,0x10);
+           SiS_LongDelay(SiS_Pr, 1);
+           SiS_SetCH701x(SiS_Pr,0x48,0x18);
 
-          if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
+          if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
              SiS_ChrontelResetVSync(SiS_Pr);
-             SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x49);
+             SiS_SetCH701x(SiS_Pr,0x49,temp);
           }
 
         } else {
@@ -8638,72 +8460,72 @@ SiS_ChrontelResetDB(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
           /* Clear/set/clear GPIO */
            temp = SiS_GetCH701x(SiS_Pr,0x5c);
           temp &= 0xef;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+          SiS_SetCH701x(SiS_Pr,0x5c,temp);
           temp = SiS_GetCH701x(SiS_Pr,0x5c);
           temp |= 0x10;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+          SiS_SetCH701x(SiS_Pr,0x5c,temp);
           temp = SiS_GetCH701x(SiS_Pr,0x5c);
           temp &= 0xef;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x5c);
+          SiS_SetCH701x(SiS_Pr,0x5c,temp);
           temp = SiS_GetCH701x(SiS_Pr,0x61);
           if(!temp) {
-             SiS_SetCH701xForLCD(SiS_Pr, HwInfo);
+             SiS_SetCH701xForLCD(SiS_Pr);
           }
         }
 
      } else { /* 650 */
         /* Reset Chrontel 7019 datapath */
-        SiS_SetCH701x(SiS_Pr,0x1048);
-        SiS_LongDelay(SiS_Pr,1);
-        SiS_SetCH701x(SiS_Pr,0x1848);
+        SiS_SetCH701x(SiS_Pr,0x48,0x10);
+        SiS_LongDelay(SiS_Pr, 1);
+        SiS_SetCH701x(SiS_Pr,0x48,0x18);
      }
 }
 
 static void
-SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr)
 {
-     USHORT temp;
+     unsigned short temp;
 
-     if(HwInfo->jChipType == SIS_740) {
+     if(SiS_Pr->ChipType == SIS_740) {
 
-        if(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo)) {
+        if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
            SiS_ChrontelResetVSync(SiS_Pr);
         }
 
      } else {
 
-        SiS_SetCH701x(SiS_Pr,0xaf76);  /* Power up LVDS block */
+        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* Power up LVDS block */
         temp = SiS_GetCH701x(SiS_Pr,0x49);
         temp &= 1;
         if(temp != 1) {  /* TV block powered? (0 = yes, 1 = no) */
           temp = SiS_GetCH701x(SiS_Pr,0x47);
           temp &= 0x70;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);  /* enable VSYNC */
-          SiS_LongDelay(SiS_Pr,3);
+          SiS_SetCH701x(SiS_Pr,0x47,temp);  /* enable VSYNC */
+          SiS_LongDelay(SiS_Pr, 3);
           temp = SiS_GetCH701x(SiS_Pr,0x47);
           temp |= 0x80;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x47);  /* disable VSYNC */
+          SiS_SetCH701x(SiS_Pr,0x47,temp);  /* disable VSYNC */
         }
 
      }
 }
 
 static void
-SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-     USHORT temp,temp1;
+     unsigned short temp,temp1;
 
-     if(HwInfo->jChipType == SIS_740) {
+     if(SiS_Pr->ChipType == SIS_740) {
 
         temp = SiS_GetCH701x(SiS_Pr,0x61);
         if(temp < 1) {
            temp++;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+          SiS_SetCH701x(SiS_Pr,0x61,temp);
         }
-        SiS_SetCH701x(SiS_Pr,0x4566);  /* Panel power on */
-        SiS_SetCH701x(SiS_Pr,0xaf76);  /* All power on */
-        SiS_LongDelay(SiS_Pr,1);
-        SiS_GenericDelay(SiS_Pr,0x16ff);
+        SiS_SetCH701x(SiS_Pr,0x66,0x45);  /* Panel power on */
+        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on */
+        SiS_LongDelay(SiS_Pr, 1);
+        SiS_GenericDelay(SiS_Pr, 5887);
 
      } else {  /* 650 */
 
@@ -8711,38 +8533,38 @@ SiS_ChrontelDoSomething3(SiS_Private *SiS_Pr, USHORT ModeNo, PSIS_HW_INFO HwInfo
         temp = SiS_GetCH701x(SiS_Pr,0x61);
         if(temp < 2) {
            temp++;
-          SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x61);
+          SiS_SetCH701x(SiS_Pr,0x61,temp);
           temp1 = 1;
         }
-        SiS_SetCH701x(SiS_Pr,0xac76);
+        SiS_SetCH701x(SiS_Pr,0x76,0xac);
         temp = SiS_GetCH701x(SiS_Pr,0x66);
         temp |= 0x5f;
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
+        SiS_SetCH701x(SiS_Pr,0x66,temp);
         if(ModeNo > 0x13) {
-           if(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo)) {
-             SiS_GenericDelay(SiS_Pr,0x3ff);
+           if(SiS_WeHaveBacklightCtrl(SiS_Pr)) {
+             SiS_GenericDelay(SiS_Pr, 1023);
           } else {
-             SiS_GenericDelay(SiS_Pr,0x2ff);
+             SiS_GenericDelay(SiS_Pr, 767);
           }
         } else {
            if(!temp1)
-             SiS_GenericDelay(SiS_Pr,0x2ff);
+             SiS_GenericDelay(SiS_Pr, 767);
         }
         temp = SiS_GetCH701x(SiS_Pr,0x76);
         temp |= 0x03;
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
+        SiS_SetCH701x(SiS_Pr,0x76,temp);
         temp = SiS_GetCH701x(SiS_Pr,0x66);
         temp &= 0x7f;
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x66);
-        SiS_LongDelay(SiS_Pr,1);
+        SiS_SetCH701x(SiS_Pr,0x66,temp);
+        SiS_LongDelay(SiS_Pr, 1);
 
      }
 }
 
 static void
-SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr)
 {
-     USHORT temp,tempcl,tempch;
+     unsigned short temp,tempcl,tempch;
 
      SiS_LongDelay(SiS_Pr, 1);
      tempcl = 3;
@@ -8753,87 +8575,87 @@ SiS_ChrontelDoSomething2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
        temp &= 0x04;  /* PLL stable? -> bail out */
        if(temp == 0x04) break;
 
-       if(HwInfo->jChipType == SIS_740) {
+       if(SiS_Pr->ChipType == SIS_740) {
           /* Power down LVDS output, PLL normal operation */
-          SiS_SetCH701x(SiS_Pr,0xac76);
+          SiS_SetCH701x(SiS_Pr,0x76,0xac);
        }
 
-       SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
+       SiS_SetCH701xForLCD(SiS_Pr);
 
        if(tempcl == 0) {
            if(tempch == 3) break;
-          SiS_ChrontelResetDB(SiS_Pr,HwInfo);
+          SiS_ChrontelResetDB(SiS_Pr);
           tempcl = 3;
           tempch++;
        }
        tempcl--;
        temp = SiS_GetCH701x(SiS_Pr,0x76);
        temp &= 0xfb;  /* Reset PLL */
-       SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
-       SiS_LongDelay(SiS_Pr,2);
+       SiS_SetCH701x(SiS_Pr,0x76,temp);
+       SiS_LongDelay(SiS_Pr, 2);
        temp = SiS_GetCH701x(SiS_Pr,0x76);
        temp |= 0x04;  /* PLL normal operation */
-       SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x76);
-       if(HwInfo->jChipType == SIS_740) {
-          SiS_SetCH701x(SiS_Pr,0xe078);        /* PLL loop filter */
+       SiS_SetCH701x(SiS_Pr,0x76,temp);
+       if(SiS_Pr->ChipType == SIS_740) {
+          SiS_SetCH701x(SiS_Pr,0x78,0xe0);     /* PLL loop filter */
        } else {
-          SiS_SetCH701x(SiS_Pr,0x6078);
+          SiS_SetCH701x(SiS_Pr,0x78,0x60);
        }
-       SiS_LongDelay(SiS_Pr,2);
+       SiS_LongDelay(SiS_Pr, 2);
     } while(0);
 
-    SiS_SetCH701x(SiS_Pr,0x0077);  /* MV? */
+    SiS_SetCH701x(SiS_Pr,0x77,0x00);  /* MV? */
 }
 
 static void
-SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr)
 {
-     USHORT temp;
+     unsigned short temp;
 
      temp = SiS_GetCH701x(SiS_Pr,0x03);
      temp |= 0x80;     /* Set datapath 1 to TV   */
      temp &= 0xbf;     /* Set datapath 2 to LVDS */
-     SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+     SiS_SetCH701x(SiS_Pr,0x03,temp);
 
-     if(HwInfo->jChipType == SIS_740) {
+     if(SiS_Pr->ChipType == SIS_740) {
 
         temp = SiS_GetCH701x(SiS_Pr,0x1c);
         temp &= 0xfb;  /* Normal XCLK phase */
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x1c);
+        SiS_SetCH701x(SiS_Pr,0x1c,temp);
 
         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2d,0x03);
 
         temp = SiS_GetCH701x(SiS_Pr,0x64);
         temp |= 0x40;  /* ? Bit not defined */
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x64);
+        SiS_SetCH701x(SiS_Pr,0x64,temp);
 
         temp = SiS_GetCH701x(SiS_Pr,0x03);
         temp &= 0x3f;  /* D1 input to both LVDS and TV */
-        SiS_SetCH701x(SiS_Pr,(temp << 8) | 0x03);
+        SiS_SetCH701x(SiS_Pr,0x03,temp);
 
        if(SiS_Pr->SiS_CustomT == CUT_ASUSL3000D) {
-          SiS_SetCH701x(SiS_Pr,0x4063); /* LVDS off */
+          SiS_SetCH701x(SiS_Pr,0x63,0x40); /* LVDS off */
           SiS_LongDelay(SiS_Pr, 1);
-          SiS_SetCH701x(SiS_Pr,0x0063); /* LVDS on */
-          SiS_ChrontelResetDB(SiS_Pr, HwInfo);
-          SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
-          SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
+          SiS_SetCH701x(SiS_Pr,0x63,0x00); /* LVDS on */
+          SiS_ChrontelResetDB(SiS_Pr);
+          SiS_ChrontelDoSomething2(SiS_Pr);
+          SiS_ChrontelDoSomething3(SiS_Pr, 0);
        } else {
            temp = SiS_GetCH701x(SiS_Pr,0x66);
            if(temp != 0x45) {
-              SiS_ChrontelResetDB(SiS_Pr, HwInfo);
-              SiS_ChrontelDoSomething2(SiS_Pr, HwInfo);
-              SiS_ChrontelDoSomething3(SiS_Pr, 0, HwInfo);
+              SiS_ChrontelResetDB(SiS_Pr);
+              SiS_ChrontelDoSomething2(SiS_Pr);
+              SiS_ChrontelDoSomething3(SiS_Pr, 0);
            }
        }
 
      } else { /* 650 */
 
-        SiS_ChrontelResetDB(SiS_Pr,HwInfo);
-        SiS_ChrontelDoSomething2(SiS_Pr,HwInfo);
+        SiS_ChrontelResetDB(SiS_Pr);
+        SiS_ChrontelDoSomething2(SiS_Pr);
         temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34);
-        SiS_ChrontelDoSomething3(SiS_Pr,temp,HwInfo);
-        SiS_SetCH701x(SiS_Pr,0xaf76);  /* All power on, LVDS normal operation */
+        SiS_ChrontelDoSomething3(SiS_Pr,temp);
+        SiS_SetCH701x(SiS_Pr,0x76,0xaf);  /* All power on, LVDS normal operation */
 
      }
 
@@ -8845,15 +8667,12 @@ SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 BOOLEAN
-SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
 #ifdef SIS300
-   UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
-#endif
-   USHORT ModeIdIndex, RefreshRateTableIndex;
-#if 0
-   USHORT temp;
+   unsigned char  *ROMAddr  = SiS_Pr->VirtualRomBase;
 #endif
+   unsigned short ModeIdIndex, RefreshRateTableIndex;
 
    SiS_Pr->SiS_SetFlag |= ProgrammingCRT2;
 
@@ -8866,37 +8685,37 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
    /* Used for shifting CR33 */
    SiS_Pr->SiS_SelectCRT2Rate = 4;
 
-   SiS_UnLockCRT2(SiS_Pr, HwInfo);
+   SiS_UnLockCRT2(SiS_Pr);
 
-   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+   RefreshRateTableIndex = SiS_GetRatePtr(SiS_Pr, ModeNo, ModeIdIndex);
 
    SiS_SaveCRT2Info(SiS_Pr,ModeNo);
 
    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_DisableBridge(SiS_Pr,HwInfo);
-      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (HwInfo->jChipType == SIS_730)) {
+      SiS_DisableBridge(SiS_Pr);
+      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) && (SiS_Pr->ChipType == SIS_730)) {
          SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,0x80);
       }
-      SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+      SiS_SetCRT2ModeRegs(SiS_Pr, ModeNo, ModeIdIndex);
    }
 
    if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-      SiS_LockCRT2(SiS_Pr, HwInfo);
+      SiS_LockCRT2(SiS_Pr);
       SiS_DisplayOn(SiS_Pr);
       return TRUE;
    }
 
-   SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+   SiS_GetCRT2Data(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 
    /* Set up Panel Link for LVDS and LCDA */
    SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_LCDVDES = 0;
    if( (SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
        ((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) ||
-       ((HwInfo->jChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)) ) {
-      SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+       ((SiS_Pr->ChipType >= SIS_315H) && (SiS_Pr->SiS_VBType & VB_SIS30xBLV)) ) {
+      SiS_GetLVDSDesData(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
    }
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "(init301: LCDHDES 0x%03x LCDVDES 0x%03x)\n", SiS_Pr->SiS_LCDHDES, SiS_Pr->SiS_LCDVDES);
   xf86DrvMsg(0, X_INFO, "(init301: HDE     0x%03x VDE     0x%03x)\n", SiS_Pr->SiS_HDE, SiS_Pr->SiS_VDE);
@@ -8907,86 +8726,79 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 #endif
 
    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, HwInfo, RefreshRateTableIndex);
+      SiS_SetGroup1(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
    }
 
    if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-        if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
 
-          SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+        SiS_SetGroup2(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 #ifdef SIS315H
-          SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+        SiS_SetGroup2_C_ELV(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 #endif
-          SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-          SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex, HwInfo);
+        SiS_SetGroup3(SiS_Pr, ModeNo, ModeIdIndex);
+        SiS_SetGroup4(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
 #ifdef SIS315H
-          SiS_SetGroup4_C_ELV(SiS_Pr, HwInfo, ModeNo, ModeIdIndex);
+        SiS_SetGroup4_C_ELV(SiS_Pr, ModeNo, ModeIdIndex);
 #endif
-          SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
+        SiS_SetGroup5(SiS_Pr, ModeNo, ModeIdIndex);
 
-          SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
 
-          /* For 301BDH (Panel link initialization): */
-          if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
-             if(SiS_Pr->SiS_LCDResInfo != Panel_640x480) {
-                if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
-                   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-                      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,
-                                      RefreshRateTableIndex,HwInfo);
-                   }
-                 }
-             }
-             SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,
-                             RefreshRateTableIndex,HwInfo);
-          }
-        }
+        /* For 301BDH (Panel link initialization): */
+        if((SiS_Pr->SiS_VBType & VB_NoLCD) && (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)) {
+
+           if(!((SiS_Pr->SiS_SetFlag & SetDOSMode) && ((ModeNo == 0x03) || (ModeNo == 0x10)))) {
+              if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
+                 SiS_ModCRT1CRTC(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+              }
+            }
+           SiS_SetCRT2ECLK(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+        }
+      }
 
    } else {
 
-        SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex, HwInfo);
+      SiS_SetCRT2Sync(SiS_Pr, ModeNo, RefreshRateTableIndex);
 
-        if(!(SiS_Pr->SiS_LCDInfo & LCDPass11)) {
-          SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
-       }
+      SiS_ModCRT1CRTC(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
 
-        SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,HwInfo);
+      SiS_SetCRT2ECLK(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
 
-       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-          if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
-             if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-                if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
+      if(SiS_Pr->SiS_SetFlag & LowModeTests) {
+        if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
+           if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+              if(SiS_Pr->SiS_IF_DEF_CH70xx == 2) {
 #ifdef SIS315H
-                   SiS_SetCH701xForLCD(SiS_Pr,HwInfo);
+                 SiS_SetCH701xForLCD(SiS_Pr);
 #endif
-                }
-             }
-             if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-                        SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
-             }
-          }
-       }
+              }
+           }
+           if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+              SiS_SetCHTVReg(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex);
+           }
+        }
+      }
 
    }
 
 #ifdef SIS300
-   if(HwInfo->jChipType < SIS_315H) {
+   if(SiS_Pr->ChipType < SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
         if(SiS_Pr->SiS_UseOEM) {
            if((SiS_Pr->SiS_UseROM) && (SiS_Pr->SiS_UseOEM == -1)) {
               if((ROMAddr[0x233] == 0x12) && (ROMAddr[0x234] == 0x34)) {
-                 SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
-                                   RefreshRateTableIndex);
+                 SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
               }
            } else {
-                      SiS_OEM300Setting(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,
-                                RefreshRateTableIndex);
+              SiS_OEM300Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
            }
         }
         if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-            if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
+           if((SiS_Pr->SiS_CustomT == CUT_BARCO1366) ||
               (SiS_Pr->SiS_CustomT == CUT_BARCO1024)) {
-              SetOEMLCDData2(SiS_Pr, HwInfo, ModeNo, ModeIdIndex,RefreshRateTableIndex);
+              SetOEMLCDData2(SiS_Pr, ModeNo, ModeIdIndex,RefreshRateTableIndex);
            }
            SiS_DisplayOn(SiS_Pr);
          }
@@ -8995,21 +8807,21 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 #endif
 
 #ifdef SIS315H
-   if(HwInfo->jChipType >= SIS_315H) {
+   if(SiS_Pr->ChipType >= SIS_315H) {
       if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-        if(HwInfo->jChipType < SIS_661) {
-           SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex, HwInfo);
-            SiS_OEM310Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+        if(SiS_Pr->ChipType < SIS_661) {
+           SiS_FinalizeLCD(SiS_Pr, ModeNo, ModeIdIndex);
+           SiS_OEM310Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
         } else {
-           SiS_OEM661Setting(SiS_Pr, HwInfo, ModeNo, ModeIdIndex, RefreshRateTableIndex);
+           SiS_OEM661Setting(SiS_Pr, ModeNo, ModeIdIndex, RefreshRateTableIndex);
         }
-         SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
+        SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x40);
       }
    }
 #endif
 
    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_EnableBridge(SiS_Pr, HwInfo);
+      SiS_EnableBridge(SiS_Pr);
    }
 
    SiS_DisplayOn(SiS_Pr);
@@ -9017,15 +8829,15 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
    if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) {
       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         /* Disable LCD panel when using TV */
-        SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFF,0x0C);
+        SiS_SetRegSR11ANDOR(SiS_Pr,0xFF,0x0C);
       } else {
         /* Disable TV when using LCD */
-        SiS_SetCH70xxANDOR(SiS_Pr,0x010E,0xF8);
+        SiS_SetCH70xxANDOR(SiS_Pr,0x0e,0x01,0xf8);
       }
    }
 
    if(SiS_Pr->SiS_SetFlag & LowModeTests) {
-      SiS_LockCRT2(SiS_Pr,HwInfo);
+      SiS_LockCRT2(SiS_Pr);
    }
 
    return TRUE;
@@ -9037,13 +8849,13 @@ SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 /*********************************************/
 
 void
-SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr)
 {
   /* Switch on LCD backlight on SiS30xLV */
   SiS_DDC2Delay(SiS_Pr,0xff00);
   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-     SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+     SiS_WaitVBRetrace(SiS_Pr);
   }
   if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x01)) {
      SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
@@ -9051,12 +8863,11 @@ SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 }
 
 void
-SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr)
 {
   /* Switch off LCD backlight on SiS30xLV */
   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-  SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-  SiS_DDC2Delay(SiS_Pr,0xe000);
+  SiS_DDC2Delay(SiS_Pr,0xff00);
 }
 
 /*********************************************/
@@ -9064,7 +8875,7 @@ SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 /*********************************************/
 
 static void
-SiS_SetupDDCN(SiS_Private *SiS_Pr)
+SiS_SetupDDCN(struct SiS_Private *SiS_Pr)
 {
   SiS_Pr->SiS_DDC_NData = ~SiS_Pr->SiS_DDC_Data;
   SiS_Pr->SiS_DDC_NClk  = ~SiS_Pr->SiS_DDC_Clk;
@@ -9075,12 +8886,12 @@ SiS_SetupDDCN(SiS_Private *SiS_Pr)
 }
 
 #ifdef SIS300
-static UCHAR *
-SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
+static unsigned char *
+SiS_SetTrumpBlockLoop(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
 {
   int i, j, num;
-  USHORT tempah,temp;
-  UCHAR *mydataptr;
+  unsigned short tempah,temp;
+  unsigned char *mydataptr;
 
   for(i=0; i<20; i++) {                                /* Do 20 attempts to write */
      mydataptr = dataptr;
@@ -9088,7 +8899,7 @@ SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
      if(!num) return mydataptr;
      if(i) {
         SiS_SetStop(SiS_Pr);
-       SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT*2);
+       SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 2);
      }
      if(SiS_SetStart(SiS_Pr)) continue;                /* Set start condition */
      tempah = SiS_Pr->SiS_DDC_DeviceAddr;
@@ -9110,12 +8921,12 @@ SiS_SetTrumpBlockLoop(SiS_Private *SiS_Pr, UCHAR *dataptr)
 }
 
 static BOOLEAN
-SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
+SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr)
 {
   SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;           /* DAB (Device Address Byte) */
   SiS_Pr->SiS_DDC_Index = 0x11;                        /* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x02;                /* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x01;                /* Bitmask in IndexReg for Clk */
+  SiS_Pr->SiS_DDC_Data  = 0x02;                        /* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x01;                        /* Bitmask in IndexReg for Clk */
   SiS_SetupDDCN(SiS_Pr);
 
   SiS_SetSwitchDDC2(SiS_Pr);
@@ -9124,8 +8935,10 @@ SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
      dataptr = SiS_SetTrumpBlockLoop(SiS_Pr, dataptr);
      if(!dataptr) return FALSE;
   }
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
   xf86DrvMsg(0, X_INFO, "Trumpion block success\n");
+#endif
 #endif
   return TRUE;
 }
@@ -9139,155 +8952,121 @@ SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr)
  */
 
 static BOOLEAN
-SiS_SetChReg(SiS_Private *SiS_Pr, USHORT tempbx, USHORT myor)
+SiS_SetChReg(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val, unsigned short myor)
 {
-  USHORT tempah,temp,i;
+  unsigned short temp, i;
 
   for(i=0; i<20; i++) {                                /* Do 20 attempts to write */
      if(i) {
-        SiS_SetStop(SiS_Pr);
-       SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
-     }
-     if(SiS_SetStart(SiS_Pr)) continue;                /* Set start condition */
-     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);  /* Write DAB (S0=0=write) */
-     if(temp) continue;                                /*    (ERROR: no ack) */
-     tempah = tempbx & 0x00FF;                 /* Write RAB */
-     tempah |= myor;                            /* (700x: set bit 7, see datasheet) */
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
-     if(temp) continue;                                /*    (ERROR: no ack) */
-     tempah = (tempbx & 0xFF00) >> 8;
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);  /* Write data */
-     if(temp) continue;                                /*    (ERROR: no ack) */
-     if(SiS_SetStop(SiS_Pr)) continue;         /* Set stop condition */
+       SiS_SetStop(SiS_Pr);
+       SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;                                        /* Set start condition */
+     temp = SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr);     /* Write DAB (S0=0=write) */
+     if(temp) continue;                                                        /*    (ERROR: no ack) */
+     temp = SiS_WriteDDC2Data(SiS_Pr, (reg | myor));                   /* Write RAB (700x: set bit 7, see datasheet) */
+     if(temp) continue;                                                        /*    (ERROR: no ack) */
+     temp = SiS_WriteDDC2Data(SiS_Pr, val);                            /* Write data */
+     if(temp) continue;                                                        /*    (ERROR: no ack) */
+     if(SiS_SetStop(SiS_Pr)) continue;                                 /* Set stop condition */
      SiS_Pr->SiS_ChrontelInit = 1;
      return TRUE;
   }
   return FALSE;
 }
 
-#if 0
-#ifdef SIS300
-/* Write Trumpion register */
-static void
-SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
-{
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;           /* DAB (Device Address Byte) */
-  SiS_Pr->SiS_DDC_Index = 0x11;                        /* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x02;                /* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x01;                /* Bitmask in IndexReg for Clk */
-  SiS_SetupDDCN(SiS_Pr);
-  SiS_SetChReg(SiS_Pr, tempbx, 0);
-}
-#endif
-#endif
-
 /* Write to Chrontel 700x */
-/* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
 void
-SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
 {
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;           /* DAB (Device Address Byte) */
 
+  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
   if(!(SiS_Pr->SiS_ChrontelInit)) {
      SiS_Pr->SiS_DDC_Index = 0x11;             /* Bit 0 = SC;  Bit 1 = SD */
-     SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
-     SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
+     SiS_Pr->SiS_DDC_Data  = 0x02;             /* Bitmask in IndexReg for Data */
+     SiS_Pr->SiS_DDC_Clk   = 0x01;             /* Bitmask in IndexReg for Clk */
      SiS_SetupDDCN(SiS_Pr);
   }
 
-  if( (!(SiS_SetChReg(SiS_Pr, tempbx, 0x80))) &&
+  if( (!(SiS_SetChReg(SiS_Pr, reg, val, 0x80))) &&
       (!(SiS_Pr->SiS_ChrontelInit)) ) {
-     SiS_Pr->SiS_DDC_Index = 0x0a;             /* Bit 7 = SC;  Bit 6 = SD */
-     SiS_Pr->SiS_DDC_Data  = 0x80;              /* Bitmask in IndexReg for Data */
-     SiS_Pr->SiS_DDC_Clk   = 0x40;              /* Bitmask in IndexReg for Clk */
+     SiS_Pr->SiS_DDC_Index = 0x0a;
+     SiS_Pr->SiS_DDC_Data  = 0x80;
+     SiS_Pr->SiS_DDC_Clk   = 0x40;
      SiS_SetupDDCN(SiS_Pr);
 
-     SiS_SetChReg(SiS_Pr, tempbx, 0x80);
+     SiS_SetChReg(SiS_Pr, reg, val, 0x80);
   }
 }
 
 /* Write to Chrontel 701x */
 /* Parameter is [Data (S15-S8) | Register no (S7-S0)] */
 void
-SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
 {
   SiS_Pr->SiS_DDC_Index = 0x11;                        /* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
+  SiS_Pr->SiS_DDC_Data  = 0x08;                        /* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x04;                        /* Bitmask in IndexReg for Clk */
   SiS_SetupDDCN(SiS_Pr);
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;           /* DAB (Device Address Byte) */
-  SiS_SetChReg(SiS_Pr, tempbx, 0);
+  SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;           /* DAB (Device Address Byte) */
+  SiS_SetChReg(SiS_Pr, reg, val, 0);
 }
 
-static void
-SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+void
+SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val)
 {
   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-     SiS_SetCH700x(SiS_Pr,tempbx);
+     SiS_SetCH700x(SiS_Pr, reg, val);
   else
-     SiS_SetCH701x(SiS_Pr,tempbx);
+     SiS_SetCH701x(SiS_Pr, reg, val);
 }
 
-static USHORT
-SiS_GetChReg(SiS_Private *SiS_Pr, USHORT myor)
+static unsigned short
+SiS_GetChReg(struct SiS_Private *SiS_Pr, unsigned short myor)
 {
-  USHORT tempah,temp,i;
+  unsigned short tempah, temp, i;
 
   for(i=0; i<20; i++) {                                /* Do 20 attempts to read */
      if(i) {
-        SiS_SetStop(SiS_Pr);
-       SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
-     }
-     if(SiS_SetStart(SiS_Pr)) continue;                /* Set start condition */
-     tempah = SiS_Pr->SiS_DDC_DeviceAddr;
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);  /* Write DAB (S0=0=write) */
-     if(temp) continue;                                /*        (ERROR: no ack) */
-     tempah = SiS_Pr->SiS_DDC_ReadAddr | myor; /* Write RAB (700x: | 0x80) */
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);
-     if(temp) continue;                                /*        (ERROR: no ack) */
-     if (SiS_SetStart(SiS_Pr)) continue;       /* Re-start */
-     tempah = SiS_Pr->SiS_DDC_DeviceAddr | 0x01;/* DAB | 0x01 = Read */
-     temp = SiS_WriteDDC2Data(SiS_Pr,tempah);  /* DAB (S0=1=read) */
-     if(temp) continue;                                /*        (ERROR: no ack) */
-     tempah = SiS_ReadDDC2Data(SiS_Pr,tempah); /* Read byte */
-     if(SiS_SetStop(SiS_Pr)) continue;         /* Stop condition */
+       SiS_SetStop(SiS_Pr);
+       SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT * 4);
+     }
+     if(SiS_SetStart(SiS_Pr)) continue;                                        /* Set start condition */
+     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr);      /* Write DAB (S0=0=write) */
+     if(temp) continue;                                                        /*        (ERROR: no ack) */
+     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_ReadAddr | myor); /* Write RAB (700x: | 0x80) */
+     if(temp) continue;                                                        /*        (ERROR: no ack) */
+     if (SiS_SetStart(SiS_Pr)) continue;                               /* Re-start */
+     temp = SiS_WriteDDC2Data(SiS_Pr,SiS_Pr->SiS_DDC_DeviceAddr | 0x01);/* DAB (S0=1=read) */
+     if(temp) continue;                                                        /*        (ERROR: no ack) */
+     tempah = SiS_ReadDDC2Data(SiS_Pr);                                        /* Read byte */
+     if(SiS_SetStop(SiS_Pr)) continue;                                 /* Stop condition */
      SiS_Pr->SiS_ChrontelInit = 1;
-     return(tempah);
+     return tempah;
   }
   return 0xFFFF;
 }
 
-#if 0
-#ifdef SIS300
-/* Read from Trumpion */
-static USHORT
-SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx)
-{
-  SiS_Pr->SiS_DDC_DeviceAddr = 0xF0;   /* DAB */
-  SiS_Pr->SiS_DDC_Index = 0x11;                /* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x02;         /* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x01;         /* Bitmask in IndexReg for Clk */
-  SiS_SetupDDCN(SiS_Pr);
-  SiS_Pr->SiS_DDC_ReadAddr = tempbx;
-  return(SiS_GetChReg(SiS_Pr,0));
-}
-#endif
-#endif
-
 /* Read from Chrontel 700x */
 /* Parameter is [Register no (S7-S0)] */
-USHORT
-SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
+unsigned short
+SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
 {
-  USHORT result;
+  unsigned short result;
 
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;           /* DAB */
 
+  SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
+
   if(!(SiS_Pr->SiS_ChrontelInit)) {
      SiS_Pr->SiS_DDC_Index = 0x11;             /* Bit 0 = SC;  Bit 1 = SD */
-     SiS_Pr->SiS_DDC_Data  = 0x02;              /* Bitmask in IndexReg for Data */
-     SiS_Pr->SiS_DDC_Clk   = 0x01;              /* Bitmask in IndexReg for Clk */
+     SiS_Pr->SiS_DDC_Data  = 0x02;             /* Bitmask in IndexReg for Data */
+     SiS_Pr->SiS_DDC_Clk   = 0x01;             /* Bitmask in IndexReg for Clk */
      SiS_SetupDDCN(SiS_Pr);
   }
 
@@ -9303,52 +9082,69 @@ SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx)
 
      result = SiS_GetChReg(SiS_Pr,0x80);
   }
-  return(result);
+  return result;
 }
 
 /* Read from Chrontel 701x */
 /* Parameter is [Register no (S7-S0)] */
-USHORT
-SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx)
+unsigned short
+SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempbx)
 {
   SiS_Pr->SiS_DDC_Index = 0x11;                        /* Bit 0 = SC;  Bit 1 = SD */
-  SiS_Pr->SiS_DDC_Data  = 0x08;                 /* Bitmask in IndexReg for Data */
-  SiS_Pr->SiS_DDC_Clk   = 0x04;                 /* Bitmask in IndexReg for Clk */
+  SiS_Pr->SiS_DDC_Data  = 0x08;                        /* Bitmask in IndexReg for Data */
+  SiS_Pr->SiS_DDC_Clk   = 0x04;                        /* Bitmask in IndexReg for Clk */
   SiS_SetupDDCN(SiS_Pr);
   SiS_Pr->SiS_DDC_DeviceAddr = 0xEA;           /* DAB */
 
   SiS_Pr->SiS_DDC_ReadAddr = tempbx;
 
-  return(SiS_GetChReg(SiS_Pr,0));
+  return SiS_GetChReg(SiS_Pr,0);
 }
 
 /* Read from Chrontel 70xx */
 /* Parameter is [Register no (S7-S0)] */
-static USHORT
-SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx)
+#ifdef SIS_LINUX_KERNEL
+static
+#endif
+unsigned short
+SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempbx)
 {
   if(SiS_Pr->SiS_IF_DEF_CH70xx == 1)
-     return(SiS_GetCH700x(SiS_Pr, tempbx));
+     return SiS_GetCH700x(SiS_Pr, tempbx);
   else
-     return(SiS_GetCH701x(SiS_Pr, tempbx));
+     return SiS_GetCH701x(SiS_Pr, tempbx);
+}
+
+void
+SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+               unsigned char myor, unsigned short myand)
+{
+  unsigned short tempbl;
+
+  tempbl = (SiS_GetCH70xx(SiS_Pr, (reg & 0xFF)) & myand) | myor;
+  SiS_SetCH70xx(SiS_Pr, reg, tempbl);
 }
 
 /* Our own DDC functions */
-static USHORT
-SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-                USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+                unsigned short adaptnum, unsigned short DDCdatatype, BOOLEAN checkcr32,
+               unsigned int VBFlags2)
 {
      unsigned char ddcdtype[] = { 0xa0, 0xa0, 0xa0, 0xa2, 0xa6 };
      unsigned char flag, cr32;
-     USHORT        temp = 0, myadaptnum = adaptnum;
+     unsigned short        temp = 0, myadaptnum = adaptnum;
 
      if(adaptnum != 0) {
-        if(!(VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0xFFFF;
-       if((VBFlags & VB_30xBDH) && (adaptnum == 1)) return 0xFFFF;
-     } 
-     
+       if(!(VBFlags2 & VB2_SISTMDSBRIDGE)) return 0xFFFF;
+       if((VBFlags2 & VB2_30xBDH) && (adaptnum == 1)) return 0xFFFF;
+     }
+
      /* adapternum for SiS bridges: 0 = CRT1, 1 = LCD, 2 = VGA2 */
-     
+
      SiS_Pr->SiS_ChrontelInit = 0;   /* force re-detection! */
 
      SiS_Pr->SiS_DDC_SecAddr = 0;
@@ -9360,7 +9156,7 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
      cr32 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x32);
 
 #if 0
-     if(VBFlags & VB_SISBRIDGE) {
+     if(VBFlags2 & VB2_SISBRIDGE) {
        if(myadaptnum == 0) {
           if(!(cr32 & 0x20)) {
              myadaptnum = 2;
@@ -9376,20 +9172,20 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
 #endif
 
      if(VGAEngine == SIS_300_VGA) {            /* 300 series */
-       
+
         if(myadaptnum != 0) {
           flag = 0;
-          if(VBFlags & VB_SISBRIDGE) {
+          if(VBFlags2 & VB2_SISBRIDGE) {
              SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
               SiS_Pr->SiS_DDC_Index = 0x0f;
           }
         }
 
-       if(!(VBFlags & VB_301)) {
+       if(!(VBFlags2 & VB2_301)) {
           if((cr32 & 0x80) && (checkcr32)) {
               if(myadaptnum >= 1) {
                 if(!(cr32 & 0x08)) {
-                    myadaptnum = 1;
+                    myadaptnum = 1;
                     if(!(cr32 & 0x10)) return 0xFFFF;
                  }
              }
@@ -9401,17 +9197,17 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
 
      } else {                                          /* 315/330 series */
 
-       /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
+       /* here we simplify: 0 = CRT1, 1 = CRT2 (VGA, LCD) */
 
-       if(VBFlags & VB_SISBRIDGE) {
+       if(VBFlags2 & VB2_SISBRIDGE) {
           if(myadaptnum == 2) {
              myadaptnum = 1;
-           }
+          }
        }
 
         if(myadaptnum == 1) {
-          flag = 0;
-          if(VBFlags & VB_SISBRIDGE) {
+          flag = 0;
+          if(VBFlags2 & VB2_SISBRIDGE) {
              SiS_Pr->SiS_DDC_Port = SiS_Pr->SiS_Part4Port;
               SiS_Pr->SiS_DDC_Index = 0x0f;
           }
@@ -9429,93 +9225,96 @@ SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
         temp = myadaptnum;
         if(myadaptnum == 1) {
            temp = 0;
-          if(VBFlags & VB_LVDS) flag = 0xff;
+          if(VBFlags2 & VB2_LVDS) flag = 0xff;
         }
 
        if(flag) temp = 0;
     }
-    
+
     SiS_Pr->SiS_DDC_Data = 0x02 << temp;
     SiS_Pr->SiS_DDC_Clk  = 0x01 << temp;
 
     SiS_SetupDDCN(SiS_Pr);
 
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "DDC Port %x Index %x Shift %d\n",
                SiS_Pr->SiS_DDC_Port, SiS_Pr->SiS_DDC_Index, temp);
 #endif
-    
+#endif
     return 0;
 }
 
-static USHORT
-SiS_WriteDABDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_WriteDABDDC(struct SiS_Private *SiS_Pr)
 {
    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_DeviceAddr)) {
-       return 0xFFFF;
+      return 0xFFFF;
    }
    if(SiS_WriteDDC2Data(SiS_Pr, SiS_Pr->SiS_DDC_SecAddr)) {
-       return 0xFFFF;
+      return 0xFFFF;
    }
-   return(0);
+   return 0;
 }
 
-static USHORT
-SiS_PrepareReadDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr)
 {
    if(SiS_SetStart(SiS_Pr)) return 0xFFFF;
    if(SiS_WriteDDC2Data(SiS_Pr, (SiS_Pr->SiS_DDC_DeviceAddr | 0x01))) {
-       return 0xFFFF;
+      return 0xFFFF;
    }
-   return(0);
+   return 0;
 }
 
-static USHORT
-SiS_PrepareDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_PrepareDDC(struct SiS_Private *SiS_Pr)
 {
    if(SiS_WriteDABDDC(SiS_Pr)) SiS_WriteDABDDC(SiS_Pr);
-   if(SiS_PrepareReadDDC(SiS_Pr)) return(SiS_PrepareReadDDC(SiS_Pr));
-   return(0);
+   if(SiS_PrepareReadDDC(SiS_Pr)) return (SiS_PrepareReadDDC(SiS_Pr));
+   return 0;
 }
 
 static void
-SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno)
+SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno)
 {
    SiS_SetSCLKLow(SiS_Pr);
    if(yesno) {
       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                     SiS_Pr->SiS_DDC_Index,
-                      SiS_Pr->SiS_DDC_NData,
+                     SiS_Pr->SiS_DDC_Index,
+                     SiS_Pr->SiS_DDC_NData,
                      SiS_Pr->SiS_DDC_Data);
    } else {
       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                     SiS_Pr->SiS_DDC_Index,
-                      SiS_Pr->SiS_DDC_NData,
+                     SiS_Pr->SiS_DDC_Index,
+                     SiS_Pr->SiS_DDC_NData,
                      0);
    }
    SiS_SetSCLKHigh(SiS_Pr);
 }
 
-static USHORT
-SiS_DoProbeDDC(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_DoProbeDDC(struct SiS_Private *SiS_Pr)
 {
     unsigned char mask, value;
-    USHORT  temp, ret=0;
+    unsigned short  temp, ret=0;
     BOOLEAN failed = FALSE;
 
     SiS_SetSwitchDDC2(SiS_Pr);
     if(SiS_PrepareDDC(SiS_Pr)) {
          SiS_SetStop(SiS_Pr);
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
          xf86DrvMsg(0, X_INFO, "Probe: Prepare failed\n");
 #endif
-         return(0xFFFF);
+#endif
+         return 0xFFFF;
     }
     mask = 0xf0;
     value = 0x20;
     if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
-       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
        SiS_SendACK(SiS_Pr, 0);
        if(temp == 0) {
            mask = 0xff;
@@ -9523,20 +9322,24 @@ SiS_DoProbeDDC(SiS_Private *SiS_Pr)
        } else {
            failed = TRUE;
           ret = 0xFFFF;
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
            xf86DrvMsg(0, X_INFO, "Probe: Read 1 failed\n");
+#endif
 #endif
        }
     }
     if(failed == FALSE) {
-       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+       temp = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
        SiS_SendACK(SiS_Pr, 1);
        temp &= mask;
        if(temp == value) ret = 0;
        else {
           ret = 0xFFFF;
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
           xf86DrvMsg(0, X_INFO, "Probe: Read 2 failed\n");
+#endif
 #endif
           if(SiS_Pr->SiS_DDC_DeviceAddr == 0xa0) {
              if(temp == 0x30) ret = 0;
@@ -9544,13 +9347,16 @@ SiS_DoProbeDDC(SiS_Private *SiS_Pr)
        }
     }
     SiS_SetStop(SiS_Pr);
-    return(ret);
+    return ret;
 }
 
-static USHORT
-SiS_ProbeDDC(SiS_Private *SiS_Pr)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_ProbeDDC(struct SiS_Private *SiS_Pr)
 {
-   USHORT flag;
+   unsigned short flag;
 
    flag = 0x180;
    SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;
@@ -9560,16 +9366,19 @@ SiS_ProbeDDC(SiS_Private *SiS_Pr)
    SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;
    if(!(SiS_DoProbeDDC(SiS_Pr))) flag |= 0x10;
    if(!(flag & 0x1a)) flag = 0;
-   return(flag);
+   return flag;
 }
 
-static USHORT
-SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
+#ifndef SIS_XORG_XF86
+static
+#endif
+unsigned short
+SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype, unsigned char *buffer)
 {
-   USHORT flag, length, i;
+   unsigned short flag, length, i;
    unsigned char chksum,gotcha;
 
-   if(DDCdatatype > 4) return 0xFFFF;  
+   if(DDCdatatype > 4) return 0xFFFF;
 
    flag = 0;
    SiS_SetSwitchDDC2(SiS_Pr);
@@ -9579,21 +9388,21 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
       chksum = 0;
       gotcha = 0;
       for(i=0; i<length; i++) {
-         buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+        buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
         chksum += buffer[i];
         gotcha |= buffer[i];
         SiS_SendACK(SiS_Pr, 0);
       }
-      buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr, 0);
+      buffer[i] = (unsigned char)SiS_ReadDDC2Data(SiS_Pr);
       chksum += buffer[i];
       SiS_SendACK(SiS_Pr, 1);
-      if(gotcha) flag = (USHORT)chksum;
+      if(gotcha) flag = (unsigned short)chksum;
       else flag = 0xFFFF;
    } else {
       flag = 0xFFFF;
    }
    SiS_SetStop(SiS_Pr);
-   return(flag);
+   return flag;
 }
 
 /* Our private DDC functions
@@ -9617,17 +9426,25 @@ SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer)
        if DDCdatatype = 0:  Returns supported DDC modes
 
  */
-USHORT
-SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-              USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer)
+unsigned short
+SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+              unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+             unsigned int VBFlags2)
 {
-   unsigned char sr1f,cr17=1;
-   USHORT result;
+   unsigned char  sr1f, cr17=1;
+   unsigned short result;
 
-   if(adaptnum > 2) return 0xFFFF;
-   if(DDCdatatype > 4) return 0xFFFF;
-   if((!(VBFlags & VB_VIDEOBRIDGE)) && (adaptnum > 0)) return 0xFFFF;
-   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE) == 0xFFFF) return 0xFFFF;
+   if(adaptnum > 2)
+      return 0xFFFF;
+
+   if(DDCdatatype > 4)
+      return 0xFFFF;
+
+   if((!(VBFlags2 & VB2_VIDEOBRIDGE)) && (adaptnum > 0))
+      return 0xFFFF;
+
+   if(SiS_InitDDCRegs(SiS_Pr, VBFlags, VGAEngine, adaptnum, DDCdatatype, FALSE, VBFlags2) == 0xFFFF)
+      return 0xFFFF;
 
    sr1f = SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f);
    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x1f,0x3f,0x04);
@@ -9656,10 +9473,12 @@ SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
            (buffer[4] == 0xff) && (buffer[5] == 0xff) &&
            (buffer[6] == 0xff) && (buffer[7] == 0x00) &&
            (buffer[0x12] == 1)) {
-           if(adaptnum == 1) {
-              if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
-           } else {
-              if(buffer[0x14] & 0x80)    result = 0xFFFE;
+           if(!SiS_Pr->DDCPortMixup) {
+              if(adaptnum == 1) {
+                 if(!(buffer[0x14] & 0x80)) result = 0xFFFE;
+              } else {
+                 if(buffer[0x14] & 0x80)    result = 0xFFFE;
+              }
            }
         }
       }
@@ -9671,832 +9490,10 @@ SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
    return result;
 }
 
-#ifdef LINUX_XF86
-
-static BOOLEAN
-checkedid1(unsigned char *buffer)
-{
-   /* Check header */
-   if((buffer[0] != 0x00) ||
-      (buffer[1] != 0xff) ||
-      (buffer[2] != 0xff) ||
-      (buffer[3] != 0xff) ||
-      (buffer[4] != 0xff) ||
-      (buffer[5] != 0xff) ||
-      (buffer[6] != 0xff) ||
-      (buffer[7] != 0x00))
-      return FALSE;
-
-   /* Check EDID version and revision */
-   if((buffer[0x12] != 1) || (buffer[0x13] > 4)) return FALSE;
-
-   /* Check week of manufacture for sanity */
-   if(buffer[0x10] > 53) return FALSE;
-
-   /* Check year of manufacture for sanity */
-   if(buffer[0x11] > 40) return FALSE;
-
-   return TRUE;
-}
-
-static BOOLEAN
-checkedid2(unsigned char *buffer)
-{
-   USHORT year = buffer[6] | (buffer[7] << 8);
-
-   /* Check EDID version */
-   if((buffer[0] & 0xf0) != 0x20) return FALSE;
-
-   /* Check week of manufacture for sanity */
-   if(buffer[5] > 53) return FALSE;
-
-   /* Check year of manufacture for sanity */
-   if((year != 0) && ((year < 1990) || (year > 2030))) return FALSE;
-
-   return TRUE;
-}
-
-/* Sense the LCD parameters (CR36, CR37) via DDC */
-/* SiS30x(B) only */
-USHORT
-SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS)
-{
-   USHORT DDCdatatype, paneltype, flag, xres=0, yres=0;
-   USHORT index, myindex, lumsize, numcodes, panelvendor, panelproduct;
-   int maxx=0, maxy=0, prefx=0, prefy=0;
-   unsigned char cr37=0, seekcode;
-   BOOLEAN checkexpand = FALSE;
-   BOOLEAN havesync = FALSE;
-   BOOLEAN indb = FALSE;
-   int retry, i;
-   unsigned char buffer[256];
-
-   for(i=0; i<7; i++) SiS_Pr->CP_DataValid[i] = FALSE;
-   SiS_Pr->CP_HaveCustomData = FALSE;
-   SiS_Pr->CP_MaxX = SiS_Pr->CP_MaxY = SiS_Pr->CP_MaxClock = 0;
-   SiS_Pr->CP_PreferredX = SiS_Pr->CP_PreferredY = 0;
-   SiS_Pr->CP_PreferredIndex = -1;
-   SiS_Pr->CP_PrefClock = 0;
-   SiS_Pr->PanelSelfDetected = FALSE;
-
-   if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
-   if(pSiS->VBFlags & VB_30xBDH) return 0;
-  
-   if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 1, 0, FALSE) == 0xFFFF) return 0;
-   
-   SiS_Pr->SiS_DDC_SecAddr = 0x00;
-   
-   /* Probe supported DA's */
-   flag = SiS_ProbeDDC(SiS_Pr);
-#ifdef TWDEBUG
-   xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
-       "CRT2 DDC capabilities 0x%x\n", flag);
-#endif 
-   if(flag & 0x10) {
-      SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;       /* EDID V2 (FP) */
-      DDCdatatype = 4;
-   } else if(flag & 0x08) {
-      SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;       /* EDID V2 (P&D-D Monitor) */
-      DDCdatatype = 3;
-   } else if(flag & 0x02) {
-      SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;       /* EDID V1 */
-      DDCdatatype = 1;
-   } else return 0;                            /* no DDC support (or no device attached) */
-   
-   /* Read the entire EDID */
-   retry = 2;
-   do {
-      if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "CRT2: DDC read failed (attempt %d), %s\n",
-               (3-retry), (retry == 1) ? "giving up" : "retrying");
-        retry--;
-        if(retry == 0) return 0xFFFF;
-      } else break;
-   } while(1);
-
-#ifdef TWDEBUG
-   for(i=0; i<256; i+=16) {
-       xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-       buffer[i],    buffer[i+1], buffer[i+2], buffer[i+3],
-       buffer[i+4],  buffer[i+5], buffer[i+6], buffer[i+7],
-       buffer[i+8],  buffer[i+9], buffer[i+10], buffer[i+11],
-       buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]);
-   }
-#endif   
-   
-   /* Analyze EDID and retrieve LCD panel information */
-   paneltype = 0;
-   switch(DDCdatatype) {
-   case 1:                                                     /* Analyze EDID V1 */
-      /* Catch a few clear cases: */
-      if(!(checkedid1(buffer))) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: EDID corrupt\n");
-        return 0;
-      }
-
-      if(!(buffer[0x14] & 0x80)) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: Attached display expects analog input (0x%02x)\n",
-               buffer[0x14]);
-        return 0;
-      }
-
-      if((buffer[0x18] & 0x18) != 0x08) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: Warning: Attached display is not of RGB but of %s type (0x%02x)\n",
-               ((buffer[0x18] & 0x18) == 0x00) ? "monochrome/greyscale" :
-                 ( ((buffer[0x18] & 0x18) == 0x10) ? "non-RGB multicolor" :
-                    "undefined"),
-               buffer[0x18]);
-      }
-
-      /* Now analyze the first Detailed Timing Block and see
-       * if the preferred timing mode is stored there. If so,
-       * check if this is a standard panel for which we already
-       * know the timing.
-       */
-
-      paneltype = Panel_Custom;
-      checkexpand = FALSE;
-
-      panelvendor = buffer[9] | (buffer[8] << 8);
-      panelproduct = buffer[10] | (buffer[11] << 8);
-
-      /* Overrule bogus preferred modes from database */
-      if((indb = SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
-         if(prefx) SiS_Pr->CP_PreferredX = xres = prefx;
-        if(prefy) SiS_Pr->CP_PreferredY = yres = prefy;
-      }
-
-      if(buffer[0x18] & 0x02) {
-
-         USHORT pclk = (buffer[0x36] | (buffer[0x37] << 8));
-        USHORT phb  = (buffer[0x39] | ((buffer[0x3a] & 0x0f) << 8));
-        USHORT pvb  = (buffer[0x3c] | ((buffer[0x3d] & 0x0f) << 8));
-
-        if(!xres) SiS_Pr->CP_PreferredX = xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
-         if(!yres) SiS_Pr->CP_PreferredY = yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
-
-         switch(xres) {
-#if 0      /* Treat as custom */
-            case 800:
-               if(yres == 600) {
-                  paneltype = Panel_800x600;
-                  checkexpand = TRUE;
-               }
-               break;
-#endif
-            case 1024:
-               if(yres == 768) {
-                  paneltype = Panel_1024x768;
-                  checkexpand = TRUE;
-               }
-               break;
-           case 1280:
-               if(yres == 1024) {
-                  paneltype = Panel_1280x1024;
-                  checkexpand = TRUE;
-               } else if(yres == 960) {
-                  if(pSiS->VGAEngine == SIS_300_VGA) {
-                     paneltype = Panel300_1280x960;
-                  } else {
-                     paneltype = Panel310_1280x960;
-                  }
-               } else if(yres == 768) {
-                  if( (pclk == 8100) &&
-                      (phb == (1688 - 1280)) &&
-                      (pvb == (802 - 768)) ) {
-                     paneltype = Panel_1280x768;
-                     checkexpand = FALSE;
-                     cr37 |= 0x10;
-                  }
-               } else if(yres == 800) {
-                  if( (pclk == 6900) &&
-                      (phb == (1408 - 1280)) &&
-                      (pvb == (816 - 800)) ) {
-                     paneltype = Panel_1280x800;
-                  }
-               }
-               break;
-           case 1400:
-               if(pSiS->VGAEngine == SIS_315_VGA) {
-                  if(yres == 1050) {
-                     paneltype = Panel310_1400x1050;
-                     checkexpand = TRUE;
-                  }
-               }
-               break;
-           case 1600:
-               if(pSiS->VGAEngine == SIS_315_VGA) {
-                  if(pSiS->VBFlags & VB_301C) {
-                     if(yres == 1200) {
-                        paneltype = Panel310_1600x1200;
-                        checkexpand = TRUE;
-                     }
-                  }
-               }
-               break;
-         }
-
-        /* Save sync: This is used if "Pass 1:1" is off; in this case
-         * we always use the panel's native mode = this "preferred mode"
-         * we just have been analysing. Hence, we also need its sync.
-         */
-        if((buffer[0x47] & 0x18) == 0x18) {
-           cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
-           havesync = TRUE;
-        } else {
-           /* What now? There is no digital separate output timing... */
-           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
-                  "LCD sense: Unable to retrieve Sync polarity information\n");
-           cr37 |= 0xc0;  /* Default */
-        }
-
-      }
-
-      /* Check against our database; eg. Sanyo Z2 projector reports
-       * 1024x768 as preferred mode, although it supports 1280x720
-       * natively in non-HDCP mode. Treat such wrongly reporting
-       * panels as custom and fixup actual maximum resolutions.
-       */
-      if(paneltype != Panel_Custom) {
-         if(indb) {
-           paneltype = Panel_Custom;
-           SiS_Pr->CP_MaxX = maxx;
-           SiS_Pr->CP_MaxY = maxy;
-           /* Leave preferred unchanged (MUST contain a valid mode!) */
-        }
-      }
-
-      /* If we still don't know what panel this is, we take it
-       * as a custom panel and derive the timing data from the
-       * detailed timing blocks
-       */
-      if(paneltype == Panel_Custom) {
-
-        int i, temp, base = 0x36;
-        unsigned long estpack;
-        const unsigned short estx[] = {
-               720, 720, 640, 640, 640, 640, 800, 800,
-               800, 800, 832,1024,1024,1024,1024,1280,
-               1152
-        };
-        const unsigned short esty[] = {
-               400, 400, 480, 480, 480, 480, 600, 600,
-               600, 600, 624, 768, 768, 768, 768,1024,
-               870
-        };
-        const int estclk[] = {
-                   0,     0, 25100,   0, 31500, 31500, 36100, 40000,
-               50100, 49500,     0,   0, 65100, 75200, 78700,135200,
-               0
-        };
-
-        paneltype = 0;
-        SiS_Pr->CP_Supports64048075 = TRUE;
-
-        /* Find the maximum resolution */
-
-        /* 1. From Established timings */
-        estpack = (buffer[0x23] << 9) | (buffer[0x24] << 1) | ((buffer[0x25] >> 7) & 0x01);
-        for(i=16; i>=0; i--) {
-            if(estpack & (1 << i)) {
-               if(estx[16 - i] > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = estx[16 - i];
-               if(esty[16 - i] > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = esty[16 - i];
-               if(estclk[16 - i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = estclk[16 - i];
-            }
-        }
-
-        /* By default we drive the LCD at 75Hz in 640x480 mode; if
-         * the panel does not provide this mode, use 60hz
-         */
-        if(!(buffer[0x23] & 0x04)) SiS_Pr->CP_Supports64048075 = FALSE;
-
-        /* 2. From Standard Timings */
-        for(i=0x26; i < 0x36; i+=2) {
-           if((buffer[i] != 0x01) && (buffer[i+1] != 0x01)) {
-              temp = (buffer[i] + 31) * 8;
-              if(temp > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = temp;
-              switch((buffer[i+1] & 0xc0) >> 6) {
-              case 0x03: temp = temp * 9 / 16; break;
-              case 0x02: temp = temp * 4 / 5;  break;
-              case 0x01: temp = temp * 3 / 4;  break;
-              }
-              if(temp > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = temp;
-           }
-        }
-
-        /* Now extract the Detailed Timings and convert them into modes */
-
-         for(i = 0; i < 4; i++, base += 18) {
-
-           /* Is this a detailed timing block or a monitor descriptor? */
-           if(buffer[base] || buffer[base+1] || buffer[base+2]) {
-
-              xres = buffer[base+2] | ((buffer[base+4] & 0xf0) << 4);
-               yres = buffer[base+5] | ((buffer[base+7] & 0xf0) << 4);
-
-              SiS_Pr->CP_HDisplay[i] = xres;
-              SiS_Pr->CP_HSyncStart[i] = xres + (buffer[base+8] | ((buffer[base+11] & 0xc0) << 2));
-               SiS_Pr->CP_HSyncEnd[i]   = SiS_Pr->CP_HSyncStart[i] + (buffer[base+9] | ((buffer[base+11] & 0x30) << 4));
-              SiS_Pr->CP_HTotal[i] = xres + (buffer[base+3] | ((buffer[base+4] & 0x0f) << 8));
-              SiS_Pr->CP_HBlankStart[i] = xres + 1;
-              SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
-
-              SiS_Pr->CP_VDisplay[i] = yres;
-               SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[base+10] & 0xf0) >> 4) | ((buffer[base+11] & 0x0c) << 2));
-               SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[base+10] & 0x0f) | ((buffer[base+11] & 0x03) << 4));
-              SiS_Pr->CP_VTotal[i] = yres + (buffer[base+6] | ((buffer[base+7] & 0x0f) << 8));
-              SiS_Pr->CP_VBlankStart[i] = yres + 1;
-              SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
-
-              SiS_Pr->CP_Clock[i] = (buffer[base] | (buffer[base+1] << 8)) * 10;
-
-              SiS_Pr->CP_DataValid[i] = TRUE;
-
-              /* Sort out invalid timings, interlace and too high clocks */
-              if((SiS_Pr->CP_HDisplay[i] & 7)                                            ||
-                 (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i])                     ||
-                 (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i])                      ||
-                 (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i])                        ||
-                 (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i])                    ||
-                 (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i])                       ||
-                 (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i])                         ||
-                 (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i])                     ||
-                 (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i])                      ||
-                 (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i])                        ||
-                 (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i])                     ||
-                 (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i])                       ||
-                 (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i])                         ||
-                 (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
-                  ((!(pSiS->VBFlags & VB_301C)) &&
-                   ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024) ||
-                    (SiS_Pr->CP_HDisplay[i] > 1600))))                                   ||
-                 (buffer[base+17] & 0x80)) {
-
-                 SiS_Pr->CP_DataValid[i] = FALSE;
-
-              } else {
-
-                 SiS_Pr->CP_HaveCustomData = TRUE;
-
-                 if(xres > SiS_Pr->CP_MaxX) SiS_Pr->CP_MaxX = xres;
-                 if(yres > SiS_Pr->CP_MaxY) SiS_Pr->CP_MaxY = yres;
-                 if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
-
-                 if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
-                    SiS_Pr->CP_PreferredIndex = i;
-                    SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
-                    SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
-                 }
-
-                 /* Extract the sync polarisation information. This only works
-                  * if the Flags indicate a digital separate output.
-                  */
-                 if((buffer[base+17] & 0x18) == 0x18) {
-                    SiS_Pr->CP_HSync_P[i] = (buffer[base+17] & 0x02) ? TRUE : FALSE;
-                    SiS_Pr->CP_VSync_P[i] = (buffer[base+17] & 0x04) ? TRUE : FALSE;
-                    SiS_Pr->CP_SyncValid[i] = TRUE;
-                    if((i == SiS_Pr->CP_PreferredIndex) && (!havesync)) {
-                       cr37 |= ((((buffer[base+17] & 0x06) ^ 0x06) << 5) | 0x20);
-                       havesync = TRUE;
-                    }
-                 } else {
-                    SiS_Pr->CP_SyncValid[i] = FALSE;
-                 }
-
-              }
-
-            } else if((!buffer[base]) && (!buffer[base+1]) && (!buffer[base+2]) && (!buffer[base+4])) {
-
-              /* Maximum pixclock from Monitor Range Limits */
-              if((buffer[base+3] == 0xfd) && (buffer[base+9] != 0xff)) {
-                 int maxclk = buffer[base+9] * 10;
-                 /* More than 170 is not supported anyway */
-                 if(maxclk <= 170) SiS_Pr->CP_MaxClock = maxclk * 1000;
-              }
-
-           }
-
-        }
-
-        if(SiS_Pr->CP_MaxX && SiS_Pr->CP_MaxY) {
-           paneltype = Panel_Custom;
-           checkexpand = FALSE;
-           cr37 |= 0x10;
-           SiS_Pr->CP_Vendor = panelvendor;
-           SiS_Pr->CP_Product = panelproduct;
-        }
-
-      }
-
-      if(paneltype && checkexpand) {
-         /* If any of the Established low-res modes is supported, the
-         * panel can scale automatically. For 800x600 panels, we only 
-         * check the even lower ones.
-         */
-        if(paneltype == Panel_800x600) {
-           if(buffer[0x23] & 0xfc) cr37 |= 0x10;
-        } else {
-            if(buffer[0x23])       cr37 |= 0x10;
-        }
-      }
-       
-      break;
-      
-   case 3:                                                     /* Analyze EDID V2 */
-   case 4:
-      index = 0;
-
-      if(!(checkedid2(buffer))) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: EDID corrupt\n");
-        return 0;
-      }
-
-      if((buffer[0x41] & 0x0f) == 0x03) {
-         index = 0x42 + 3;
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: Display supports TMDS input on primary interface\n");
-      } else if((buffer[0x41] & 0xf0) == 0x30) {
-         index = 0x46 + 3;
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: Display supports TMDS input on secondary interface\n");
-      } else {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "LCD sense: Display does not support TMDS video interface (0x%02x)\n",
-               buffer[0x41]);
-        return 0;
-      }
-
-      SiS_Pr->CP_Vendor = panelvendor = buffer[2] | (buffer[1] << 8);
-      SiS_Pr->CP_Product = panelproduct = buffer[3] | (buffer[4] << 8);
-
-      paneltype = Panel_Custom;
-      SiS_Pr->CP_MaxX = SiS_Pr->CP_PreferredX = xres = buffer[0x76] | (buffer[0x77] << 8);
-      SiS_Pr->CP_MaxY = SiS_Pr->CP_PreferredY = yres = buffer[0x78] | (buffer[0x79] << 8);
-
-      switch(xres) {
-#if 0
-         case 800:
-            if(yres == 600) {
-               paneltype = Panel_800x600;
-               checkexpand = TRUE;
-            }
-            break;
-#endif
-         case 1024:
-            if(yres == 768) {
-               paneltype = Panel_1024x768;
-               checkexpand = TRUE;
-            }
-            break;
-        case 1280:
-            if(yres == 960) {
-               if(pSiS->VGAEngine == SIS_315_VGA) {
-                  paneltype = Panel310_1280x960;
-               } else {
-                  paneltype = Panel300_1280x960;
-               }
-            } else if(yres == 1024) {
-               paneltype = Panel_1280x1024;
-               checkexpand = TRUE;
-            }
-            /* 1280x768 treated as custom here */
-            break;
-        case 1400:
-            if(pSiS->VGAEngine == SIS_315_VGA) {
-               if(yres == 1050) {
-                  paneltype = Panel310_1400x1050;
-                  checkexpand = TRUE;
-               }
-            }
-            break;
-        case 1600:
-            if(pSiS->VGAEngine == SIS_315_VGA) {
-               if(pSiS->VBFlags & VB_301C) {
-                  if(yres == 1200) {
-                     paneltype = Panel310_1600x1200;
-                     checkexpand = TRUE;
-                  }
-               }
-            }
-            break;
-      }
-
-      /* Determine if RGB18 or RGB24 */
-      if(index) {
-         if((buffer[index] == 0x20) || (buffer[index] == 0x34)) {
-           cr37 |= 0x01;
-        }
-      }
-
-      if(checkexpand) {
-         /* TODO - for now, we let the panel scale */
-        cr37 |= 0x10;
-      }
-
-      /* Now seek 4-Byte Timing codes and extract sync pol info */
-      index = 0x80;
-      if(buffer[0x7e] & 0x20) {                            /* skip Luminance Table (if provided) */
-         lumsize = buffer[0x80] & 0x1f;
-        if(buffer[0x80] & 0x80) lumsize *= 3;
-        lumsize++;  /* luminance header byte */
-        index += lumsize;
-      }
-#if 0 /* "pixel rate" = pixel clock? */
-      if(buffer[0x7e] & 0x1c) {
-         for(i=0; i<((buffer[0x7e] & 0x1c) >> 2); i++) {
-           if(buffer[index + (i*8) + 6] && (buffer[index + (i*8) + 7] & 0x0f)) {
-              int clk = (buffer[index + (i*8) + 6] | ((buffer[index + (i*8) + 7] & 0x0f) << 4)) * 1000;
-              if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
-           }
-        }
-      }
-#endif
-      index += (((buffer[0x7e] & 0x1c) >> 2) * 8);   /* skip Frequency Ranges */
-      if(buffer[0x7e] & 0x03) {
-         for(i=0; i<(buffer[0x7e] & 0x03); i++) {
-           if((buffer[index + (i*27) + 9]) || (buffer[index + (i*27) + 10])) {
-              int clk = ((buffer[index + (i*27) + 9]) | ((buffer[index + (i*27) + 9]) << 8)) * 10;
-              if(clk > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = clk;
-           }
-        }
-      }
-      index += ((buffer[0x7e] & 0x03) * 27);         /* skip Detailed Range Limits */
-      numcodes = (buffer[0x7f] & 0xf8) >> 3;
-      if(numcodes) {
-         myindex = index;
-        seekcode = (xres - 256) / 16;
-        for(i=0; i<numcodes; i++) {
-           if(buffer[myindex] == seekcode) break;
-           myindex += 4;
-        }
-        if(buffer[myindex] == seekcode) {
-           cr37 |= ((((buffer[myindex + 1] & 0x0c) ^ 0x0c) << 4) | 0x20);
-           havesync = TRUE;
-        } else {
-           xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
-               "LCD sense: Unable to retrieve Sync polarity information\n");
-        }
-      } else {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_WARNING,
-            "LCD sense: Unable to retrieve Sync polarity information\n");
-      }
-
-      /* Check against our database; Eg. Sanyo projector reports
-       * 1024x768 in non-HDPC mode, although it supports 1280x720.
-       * Treat such wrongly reporting panels as custom.
-       */
-      if(paneltype != Panel_Custom) {
-         int maxx, maxy, prefx, prefy;
-         if((SiS_FindPanelFromDB(pSiS, panelvendor, panelproduct, &maxx, &maxy, &prefx, &prefy))) {
-           paneltype = Panel_Custom;
-           SiS_Pr->CP_MaxX = maxx;
-           SiS_Pr->CP_MaxY = maxy;
-           cr37 |= 0x10;
-           /* Leave preferred unchanged (MUST be a valid mode!) */
-        }
-      }
-
-      /* Now seek the detailed timing descriptions for custom panels */
-      if(paneltype == Panel_Custom) {
-
-         SiS_Pr->CP_Supports64048075 = TRUE;
-
-         index += (numcodes * 4);
-        numcodes = buffer[0x7f] & 0x07;
-        for(i=0; i<numcodes; i++, index += 18) {
-           xres = buffer[index+2] | ((buffer[index+4] & 0xf0) << 4);
-            yres = buffer[index+5] | ((buffer[index+7] & 0xf0) << 4);
-
-           SiS_Pr->CP_HDisplay[i] = xres;
-           SiS_Pr->CP_HSyncStart[i] = xres + (buffer[index+8] | ((buffer[index+11] & 0xc0) << 2));
-            SiS_Pr->CP_HSyncEnd[i] = SiS_Pr->CP_HSyncStart[i] + (buffer[index+9] | ((buffer[index+11] & 0x30) << 4));
-           SiS_Pr->CP_HTotal[i] = xres + (buffer[index+3] | ((buffer[index+4] & 0x0f) << 8));
-           SiS_Pr->CP_HBlankStart[i] = xres + 1;
-           SiS_Pr->CP_HBlankEnd[i] = SiS_Pr->CP_HTotal[i];
-
-           SiS_Pr->CP_VDisplay[i] = yres;
-            SiS_Pr->CP_VSyncStart[i] = yres + (((buffer[index+10] & 0xf0) >> 4) | ((buffer[index+11] & 0x0c) << 2));
-            SiS_Pr->CP_VSyncEnd[i] = SiS_Pr->CP_VSyncStart[i] + ((buffer[index+10] & 0x0f) | ((buffer[index+11] & 0x03) << 4));
-           SiS_Pr->CP_VTotal[i] = yres + (buffer[index+6] | ((buffer[index+7] & 0x0f) << 8));
-           SiS_Pr->CP_VBlankStart[i] = yres + 1;
-           SiS_Pr->CP_VBlankEnd[i] = SiS_Pr->CP_VTotal[i];
-
-           SiS_Pr->CP_Clock[i] = (buffer[index] | (buffer[index+1] << 8)) * 10;
-
-           SiS_Pr->CP_DataValid[i] = TRUE;
-
-           if((SiS_Pr->CP_HDisplay[i] & 7)                                             ||
-              (SiS_Pr->CP_HDisplay[i] > SiS_Pr->CP_HSyncStart[i])                      ||
-              (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HSyncEnd[i])                       ||
-              (SiS_Pr->CP_HDisplay[i] >= SiS_Pr->CP_HTotal[i])                         ||
-              (SiS_Pr->CP_HSyncStart[i] >= SiS_Pr->CP_HSyncEnd[i])                     ||
-              (SiS_Pr->CP_HSyncStart[i] > SiS_Pr->CP_HTotal[i])                        ||
-              (SiS_Pr->CP_HSyncEnd[i] > SiS_Pr->CP_HTotal[i])                          ||
-              (SiS_Pr->CP_VDisplay[i] > SiS_Pr->CP_VSyncStart[i])                      ||
-              (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VSyncEnd[i])                       ||
-              (SiS_Pr->CP_VDisplay[i] >= SiS_Pr->CP_VTotal[i])                         ||
-              (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VSyncEnd[i])                      ||
-              (SiS_Pr->CP_VSyncStart[i] > SiS_Pr->CP_VTotal[i])                        ||
-              (SiS_Pr->CP_VSyncEnd[i] > SiS_Pr->CP_VTotal[i])                          ||
-              (((pSiS->VBFlags & VB_301C) && (SiS_Pr->CP_Clock[i] > 162500)) ||
-               ((!(pSiS->VBFlags & VB_301C)) &&
-                ((SiS_Pr->CP_Clock[i] > 108200) || (SiS_Pr->CP_VDisplay[i] > 1024))))  ||
-              (buffer[index + 17] & 0x80)) {
-
-              SiS_Pr->CP_DataValid[i] = FALSE;
-
-           } else {
-
-              SiS_Pr->CP_HaveCustomData = TRUE;
-
-              if(SiS_Pr->CP_Clock[i] > SiS_Pr->CP_MaxClock) SiS_Pr->CP_MaxClock = SiS_Pr->CP_Clock[i];
-
-              if((SiS_Pr->CP_PreferredX == xres) && (SiS_Pr->CP_PreferredY == yres)) {
-                 SiS_Pr->CP_PreferredIndex = i;
-                 SiS_MakeClockRegs(pSiS->pScrn, SiS_Pr->CP_Clock[i], &SiS_Pr->CP_PrefSR2B, &SiS_Pr->CP_PrefSR2C);
-                 SiS_Pr->CP_PrefClock = (SiS_Pr->CP_Clock[i] / 1000) + 1;
-                 if(!havesync) {
-                    cr37 |= ((((buffer[index + 17] & 0x06) ^ 0x06) << 5) | 0x20);
-                    havesync = TRUE;
-                 }
-              }
-
-              SiS_Pr->CP_HSync_P[i] = (buffer[index + 17] & 0x02) ? TRUE : FALSE;
-              SiS_Pr->CP_VSync_P[i] = (buffer[index + 17] & 0x04) ? TRUE : FALSE;
-              SiS_Pr->CP_SyncValid[i] = TRUE;
-
-           }
-        }
-
-        cr37 |= 0x10;
-
-      }
-
-      break;
-
-   }
-
-   /* 1280x960 panels are always RGB24, unable to scale and use
-    * high active sync polarity
-    */
-   if(pSiS->VGAEngine == SIS_315_VGA) {
-      if(paneltype == Panel310_1280x960) cr37 &= 0x0e;
-   } else {
-      if(paneltype == Panel300_1280x960) cr37 &= 0x0e;
-   }
-
-   for(i = 0; i < 7; i++) {
-      if(SiS_Pr->CP_DataValid[i]) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-            "Non-standard LCD/DVI-D timing data no. %d:\n", i);
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-           "   HDisplay %d HSync %d HSyncEnd %d HTotal %d\n",
-           SiS_Pr->CP_HDisplay[i], SiS_Pr->CP_HSyncStart[i],
-           SiS_Pr->CP_HSyncEnd[i], SiS_Pr->CP_HTotal[i]);
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-            "   VDisplay %d VSync %d VSyncEnd %d VTotal %d\n",
-            SiS_Pr->CP_VDisplay[i], SiS_Pr->CP_VSyncStart[i],
-           SiS_Pr->CP_VSyncEnd[i], SiS_Pr->CP_VTotal[i]);
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-           "   Pixel clock: %3.3fMhz\n", (float)SiS_Pr->CP_Clock[i] / 1000);
-        xf86DrvMsg(pSiS->pScrn->scrnIndex, X_INFO,
-           "   To use this, add \"%dx%d\" to the list of Modes in the Screen section\n",
-           SiS_Pr->CP_HDisplay[i],
-           SiS_Pr->CP_VDisplay[i]);
-      }
-   }
-
-   if(paneltype) {
-       if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
-       if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
-       SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
-       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
-       cr37 &= 0xf1;
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
-       SiS_Pr->PanelSelfDetected = TRUE;
-#ifdef TWDEBUG
-       xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
-                  "LCD sense: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
-#endif 
-   } else {
-       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
-       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
-   }
-   return 0;
-}
-   
-USHORT
-SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS)
-{
-   USHORT DDCdatatype,flag;
-   BOOLEAN foundcrt = FALSE;
-   int retry;
-   unsigned char buffer[256];
-
-   if(!(pSiS->VBFlags & (VB_301|VB_301B|VB_301C|VB_302B))) return 0;
-
-   if(SiS_InitDDCRegs(SiS_Pr, pSiS->VBFlags, pSiS->VGAEngine, 2, 0, FALSE) == 0xFFFF) return 0;
-   
-   SiS_Pr->SiS_DDC_SecAddr = 0x00;
-   
-   /* Probe supported DA's */
-   flag = SiS_ProbeDDC(SiS_Pr);
-   if(flag & 0x10) {
-      SiS_Pr->SiS_DDC_DeviceAddr = 0xa6;       /* EDID V2 (FP) */
-      DDCdatatype = 4;
-   } else if(flag & 0x08) {
-      SiS_Pr->SiS_DDC_DeviceAddr = 0xa2;       /* EDID V2 (P&D-D Monitor) */
-      DDCdatatype = 3;
-   } else if(flag & 0x02) {
-      SiS_Pr->SiS_DDC_DeviceAddr = 0xa0;       /* EDID V1 */
-      DDCdatatype = 1;
-   } else {
-       xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "VGA2 sense: Do DDC answer\n");
-       return 0;                               /* no DDC support (or no device attached) */
-   }
-
-   /* Read the entire EDID */
-   retry = 2;
-   do {
-      if(SiS_ReadDDC(SiS_Pr, DDCdatatype, buffer)) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_PROBED,
-               "VGA2 sense: DDC read failed (attempt %d), %s\n",
-               (3-retry), (retry == 1) ? "giving up" : "retrying");
-        retry--;
-        if(retry == 0) return 0xFFFF;
-      } else break;
-   } while(1);
-
-   /* Analyze EDID. We don't have many chances to
-    * distinguish a flat panel from a CRT...
-    */
-   switch(DDCdatatype) {
-   case 1:
-      if(!(checkedid1(buffer))) {
-          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
-               "VGA2 sense: EDID corrupt\n");
-         return 0;
-      }
-      if(buffer[0x14] & 0x80) {                        /* Display uses digital input */
-          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
-               "VGA2 sense: Attached display expects digital input\n");
-         return 0;
-      }
-      SiS_Pr->CP_Vendor = buffer[9] | (buffer[8] << 8);
-      SiS_Pr->CP_Product = buffer[10] | (buffer[11] << 8);
-      foundcrt = TRUE;
-      break;
-   case 3:
-   case 4:
-      if(!(checkedid2(buffer))) {
-          xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
-               "VGA2 sense: EDID corrupt\n");
-         return 0;
-      }
-      if( ((buffer[0x41] & 0x0f) != 0x01) &&   /* Display does not support analog input */
-          ((buffer[0x41] & 0x0f) != 0x02) &&
-         ((buffer[0x41] & 0xf0) != 0x10) &&
-         ((buffer[0x41] & 0xf0) != 0x20) ) {
-         xf86DrvMsg(pSiS->pScrn->scrnIndex, X_ERROR,
-               "VGA2 sense: Attached display does not support analog input (0x%02x)\n",
-               buffer[0x41]);
-         return 0;
-      }
-      SiS_Pr->CP_Vendor = buffer[2] | (buffer[1] << 8);
-      SiS_Pr->CP_Product = buffer[3] | (buffer[4] << 8);
-      foundcrt = TRUE;
-      break;
-   }
-
-   if(foundcrt) {
-      SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x10);
-   }
-   return(0);
-}
-
-#endif
-
-void
-SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh)
-{
-  USHORT tempbl;
-
-  tempbl = SiS_GetCH70xx(SiS_Pr,(tempax & 0x00FF));
-  tempbl = (((tempbl & tempbh) << 8) | tempax);
-  SiS_SetCH70xx(SiS_Pr,tempbl);
-}
-
 /* Generic I2C functions for Chrontel & DDC --------- */
 
 static void
-SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
+SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr)
 {
   SiS_SetSCLKHigh(SiS_Pr);
   SiS_WaitRetrace1(SiS_Pr);
@@ -10505,124 +9502,126 @@ SiS_SetSwitchDDC2(SiS_Private *SiS_Pr)
   SiS_WaitRetrace1(SiS_Pr);
 }
 
-USHORT
-SiS_ReadDDC1Bit(SiS_Private *SiS_Pr)
+unsigned short
+SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr)
 {
    SiS_WaitRetrace1(SiS_Pr);
-   return((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
+   return ((SiS_GetReg(SiS_Pr->SiS_P3c4,0x11) & 0x02) >> 1);
 }
 
 /* Set I2C start condition */
 /* This is done by a SD high-to-low transition while SC is high */
-static USHORT
-SiS_SetStart(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetStart(struct SiS_Private *SiS_Pr)
 {
-  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                               /* (SC->low)  */
+  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                    /* (SC->low)  */
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NData,
-                 SiS_Pr->SiS_DDC_Data);                                   /* SD->high */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                              /* SC->high */
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NData,
+                 SiS_Pr->SiS_DDC_Data);                        /* SD->high */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                   /* SC->high */
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NData,
-                 0x00);                                                   /* SD->low = start condition */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                              /* (SC->low) */
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NData,
+                 0x00);                                        /* SD->low = start condition */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                   /* (SC->low) */
   return 0;
 }
 
 /* Set I2C stop condition */
 /* This is done by a SD low-to-high transition while SC is high */
-static USHORT
-SiS_SetStop(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetStop(struct SiS_Private *SiS_Pr)
 {
-  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                               /* (SC->low) */
+  if(SiS_SetSCLKLow(SiS_Pr)) return 0xFFFF;                    /* (SC->low) */
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NData,
-                 0x00);                                                   /* SD->low   */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                              /* SC->high  */
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NData,
+                 0x00);                                        /* SD->low   */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                   /* SC->high  */
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NData,
-                 SiS_Pr->SiS_DDC_Data);                                   /* SD->high = stop condition */
-  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                              /* (SC->high) */
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NData,
+                 SiS_Pr->SiS_DDC_Data);                        /* SD->high = stop condition */
+  if(SiS_SetSCLKHigh(SiS_Pr)) return 0xFFFF;                   /* (SC->high) */
   return 0;
 }
 
 /* Write 8 bits of data */
-static USHORT
-SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+static unsigned short
+SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax)
 {
-  USHORT i,flag,temp;
+  unsigned short i,flag,temp;
 
   flag = 0x80;
-  for(i=0; i<8; i++) {
-    SiS_SetSCLKLow(SiS_Pr);                                                  /* SC->low */
+  for(i = 0; i < 8; i++) {
+    SiS_SetSCLKLow(SiS_Pr);                                    /* SC->low */
     if(tempax & flag) {
       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                     SiS_Pr->SiS_DDC_Index,
-                      SiS_Pr->SiS_DDC_NData,
-                     SiS_Pr->SiS_DDC_Data);                                  /* Write bit (1) to SD */
+                     SiS_Pr->SiS_DDC_Index,
+                     SiS_Pr->SiS_DDC_NData,
+                     SiS_Pr->SiS_DDC_Data);                    /* Write bit (1) to SD */
     } else {
       SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                     SiS_Pr->SiS_DDC_Index,
-                      SiS_Pr->SiS_DDC_NData,
-                     0x00);                                                  /* Write bit (0) to SD */
+                     SiS_Pr->SiS_DDC_Index,
+                     SiS_Pr->SiS_DDC_NData,
+                     0x00);                                    /* Write bit (0) to SD */
     }
-    SiS_SetSCLKHigh(SiS_Pr);                                                 /* SC->high */
+    SiS_SetSCLKHigh(SiS_Pr);                                   /* SC->high */
     flag >>= 1;
   }
-  temp = SiS_CheckACK(SiS_Pr);                                               /* Check acknowledge */
-  return(temp);
+  temp = SiS_CheckACK(SiS_Pr);                                 /* Check acknowledge */
+  return temp;
 }
 
-static USHORT
-SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax)
+static unsigned short
+SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr)
 {
-  USHORT i,temp,getdata;
+  unsigned short i, temp, getdata;
 
-  getdata=0;
-  for(i=0; i<8; i++) {
+  getdata = 0;
+  for(i = 0; i < 8; i++) {
     getdata <<= 1;
     SiS_SetSCLKLow(SiS_Pr);
     SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                   SiS_Pr->SiS_DDC_Index,
-                    SiS_Pr->SiS_DDC_NData,
+                   SiS_Pr->SiS_DDC_Index,
+                   SiS_Pr->SiS_DDC_NData,
                    SiS_Pr->SiS_DDC_Data);
     SiS_SetSCLKHigh(SiS_Pr);
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
     if(temp & SiS_Pr->SiS_DDC_Data) getdata |= 0x01;
   }
-  return(getdata);
+  return getdata;
 }
 
-static USHORT
-SiS_SetSCLKLow(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetSCLKLow(struct SiS_Private *SiS_Pr)
 {
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NClk,
-                 0x00);                                        /* SetSCLKLow()  */
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NClk,
+                 0x00);                                        /* SetSCLKLow()  */
   SiS_DDC2Delay(SiS_Pr,SiS_I2CDELAYSHORT);
   return 0;
 }
 
-static USHORT
-SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr)
 {
-  USHORT temp, watchdog=1000;
+  unsigned short temp, watchdog=1000;
 
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NClk,
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NClk,
                  SiS_Pr->SiS_DDC_Clk);                         /* SetSCLKHigh()  */
   do {
     temp = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index);
   } while((!(temp & SiS_Pr->SiS_DDC_Clk)) && --watchdog);
   if (!watchdog) {
+#ifdef SIS_XORG_XF86
 #ifdef TWDEBUG
         xf86DrvMsg(0, X_INFO, "SetClkHigh failed\n");
+#endif
 #endif
        return 0xFFFF;
   }
@@ -10632,21 +9631,21 @@ SiS_SetSCLKHigh(SiS_Private *SiS_Pr)
 
 /* Check I2C acknowledge */
 /* Returns 0 if ack ok, non-0 if ack not ok */
-static USHORT
-SiS_CheckACK(SiS_Private *SiS_Pr)
+static unsigned short
+SiS_CheckACK(struct SiS_Private *SiS_Pr)
 {
-  USHORT tempah;
+  unsigned short tempah;
 
   SiS_SetSCLKLow(SiS_Pr);                                         /* (SC->low) */
   SiS_SetRegANDOR(SiS_Pr->SiS_DDC_Port,
-                 SiS_Pr->SiS_DDC_Index,
-                  SiS_Pr->SiS_DDC_NData,
-                 SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
+                 SiS_Pr->SiS_DDC_Index,
+                 SiS_Pr->SiS_DDC_NData,
+                 SiS_Pr->SiS_DDC_Data);                           /* (SD->high) */
   SiS_SetSCLKHigh(SiS_Pr);                                        /* SC->high = clock impulse for ack */
   tempah = SiS_GetReg(SiS_Pr->SiS_DDC_Port,SiS_Pr->SiS_DDC_Index); /* Read SD */
   SiS_SetSCLKLow(SiS_Pr);                                         /* SC->low = end of clock impulse */
-  if(tempah & SiS_Pr->SiS_DDC_Data) return(1);                    /* Ack OK if bit = 0 */
-  else return(0);
+  if(tempah & SiS_Pr->SiS_DDC_Data) return 1;                     /* Ack OK if bit = 0 */
+  return 0;
 }
 
 /* End of I2C functions ----------------------- */
@@ -10656,67 +9655,67 @@ SiS_CheckACK(SiS_Private *SiS_Pr)
 
 #ifdef SIS315H
 
-static USHORT
-GetRAMDACromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetRAMDACromptr(struct SiS_Private *SiS_Pr)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT romptr;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short romptr;
 
-  if(HwInfo->jChipType < SIS_330) {
+  if(SiS_Pr->ChipType < SIS_330) {
      romptr = SISGETROMW(0x128);
-     if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
         romptr = SISGETROMW(0x12a);
   } else {
      romptr = SISGETROMW(0x1a8);
-     if(SiS_Pr->SiS_VBType & VB_SIS301B302B)
+     if(SiS_Pr->SiS_VBType & VB_SIS30xB)
         romptr = SISGETROMW(0x1aa);
   }
-  return(romptr);
+  return romptr;
 }
 
-static USHORT
-GetLCDromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDromptr(struct SiS_Private *SiS_Pr)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT romptr;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short romptr;
 
-  if(HwInfo->jChipType < SIS_330) {
+  if(SiS_Pr->ChipType < SIS_330) {
      romptr = SISGETROMW(0x120);
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
         romptr = SISGETROMW(0x122);
   } else {
      romptr = SISGETROMW(0x1a0);
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
         romptr = SISGETROMW(0x1a2);
   }
-  return(romptr);
+  return romptr;
 }
 
-static USHORT
-GetTVromptr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetTVromptr(struct SiS_Private *SiS_Pr)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT romptr;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short romptr;
 
-  if(HwInfo->jChipType < SIS_330) {
+  if(SiS_Pr->ChipType < SIS_330) {
      romptr = SISGETROMW(0x114);
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
         romptr = SISGETROMW(0x11a);
   } else {
      romptr = SISGETROMW(0x194);
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV)
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV)
         romptr = SISGETROMW(0x19a);
   }
-  return(romptr);
+  return romptr;
 }
 
-static USHORT
-GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+static unsigned short
+GetLCDPtrIndexBIOS(struct SiS_Private *SiS_Pr)
 {
-  USHORT index;
+  unsigned short index;
 
-  if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
-     if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+  if((IS_SIS650) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+     if(!(SiS_IsNotM650orLater(SiS_Pr))) {
         if((index = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0)) {
           index >>= 4;
           index *= 3;
@@ -10729,7 +9728,12 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
   index = SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F;
   if(SiS_Pr->SiS_LCDResInfo == Panel_1400x1050)      index -= 5;
-  else if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+  if(SiS_Pr->SiS_VBType & VB_SIS301C) {  /* 1.15.20 and later (not VB specific) */
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 5;
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1280x768) index -= 5;
+  } else {
+     if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) index -= 6;
+  }
   index--;
   index *= 3;
   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) index += 2;
@@ -10737,10 +9741,10 @@ GetLCDPtrIndexBIOS(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
   return index;
 }
 
-static USHORT
-GetLCDPtrIndex(SiS_Private *SiS_Pr)
+static unsigned short
+GetLCDPtrIndex(struct SiS_Private *SiS_Pr)
 {
-  USHORT index;
+  unsigned short index;
 
   index = ((SiS_GetBIOSLCDResInfo(SiS_Pr) & 0x0F) - 1) * 3;
   if(SiS_Pr->SiS_LCDInfo & DontExpandLCD)         index += 2;
@@ -10748,10 +9752,10 @@ GetLCDPtrIndex(SiS_Private *SiS_Pr)
   return index;
 }
 
-static USHORT
-GetTVPtrIndex(SiS_Private *SiS_Pr)
+static unsigned short
+GetTVPtrIndex(struct SiS_Private *SiS_Pr)
 {
-  USHORT index;
+  unsigned short index;
 
   index = 0;
   if(SiS_Pr->SiS_TVMode & TVSetPAL) index = 1;
@@ -10769,10 +9773,10 @@ GetTVPtrIndex(SiS_Private *SiS_Pr)
   return index;
 }
 
-static ULONG
-GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
+static unsigned int
+GetOEMTVPtr661_2_GEN(struct SiS_Private *SiS_Pr, int addme)
 {
-   USHORT index = 0, temp = 0;
+   unsigned short index = 0, temp = 0;
 
    if(SiS_Pr->SiS_TVMode & TVSetPAL)   index = 1;
    if(SiS_Pr->SiS_TVMode & TVSetPALM)  index = 2;
@@ -10784,7 +9788,7 @@ GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
       if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) index = 7;
    }
 
-   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+   if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
       if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) ||
          (SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
         index += addme;
@@ -10792,25 +9796,25 @@ GetOEMTVPtr661_2_GEN(SiS_Private *SiS_Pr, int addme)
       }
       temp += 0x0100;
    }
-   return(ULONG)(index | (temp << 16));
+   return (unsigned int)(index | (temp << 16));
 }
 
-static ULONG
-GetOEMTVPtr661_2_OLD(SiS_Private *SiS_Pr)
+static unsigned int
+GetOEMTVPtr661_2_OLD(struct SiS_Private *SiS_Pr)
 {
-   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
+   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 8));
 }
 
 #if 0
-static ULONG
-GetOEMTVPtr661_2_NEW(SiS_Private *SiS_Pr)
+static unsigned int
+GetOEMTVPtr661_2_NEW(struct SiS_Private *SiS_Pr)
 {
-   return(GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
+   return (GetOEMTVPtr661_2_GEN(SiS_Pr, 6));
 }
 #endif
 
 static int
-GetOEMTVPtr661(SiS_Private *SiS_Pr)
+GetOEMTVPtr661(struct SiS_Private *SiS_Pr)
 {
    int index = 0;
 
@@ -10833,10 +9837,10 @@ GetOEMTVPtr661(SiS_Private *SiS_Pr)
 }
 
 static void
-SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
+SetDelayComp(struct SiS_Private *SiS_Pr, unsigned short ModeNo)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT delay=0,index,myindex,temp,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short delay=0,index,myindex,temp,romptr=0;
   BOOLEAN dochiptest = TRUE;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -10848,19 +9852,19 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
   /* Find delay (from ROM, internal tables, PCI subsystem) */
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {                   /* ------------ VGA */
-     
+
      if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
-        romptr = GetRAMDACromptr(SiS_Pr, HwInfo);
+        romptr = GetRAMDACromptr(SiS_Pr);
      }
      if(romptr) delay = ROMAddr[romptr];
      else {
         delay = 0x04;
-        if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+        if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
           if(IS_SIS650) {
              delay = 0x0a;
           } else if(IS_SIS740) {
              delay = 0x00;
-          } else if(HwInfo->jChipType < SIS_330) {
+          } else if(SiS_Pr->ChipType < SIS_330) {
              delay = 0x0c;
           } else {
              delay = 0x0c;
@@ -10901,8 +9905,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
           SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2d,0x0f,delay);
        } else {
           delay = 0x0c;
-          if(SiS_Pr->SiS_VBType & VB_SIS301C) delay = 0x03;
-          else if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+          if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+             delay = 0x03;
+             if((SiS_Pr->PanelXRes > 1280) && (SiS_Pr->PanelYRes > 1024)) {
+                delay = 0x00;
+             }
+          } else if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
              if(IS_SIS740) delay = 0x01;
              else          delay = 0x03;
           }
@@ -10947,12 +9955,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 
      if(!gotitfrompci) {
 
-        index = GetLCDPtrIndexBIOS(SiS_Pr, HwInfo);
+        index = GetLCDPtrIndexBIOS(SiS_Pr);
         myindex = GetLCDPtrIndex(SiS_Pr);
 
-        if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+        if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
 
-           if(SiS_IsNotM650orLater(SiS_Pr, HwInfo)) {
+           if(SiS_IsNotM650orLater(SiS_Pr)) {
 
               if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
                 /* Always use the second pointer on 650; some BIOSes */
@@ -10978,11 +9986,12 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
                  (!(SiS_Pr->SiS_ROMNew))                     &&
                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) &&
                  (SiS_Pr->SiS_LCDResInfo != Panel_1280x768)  &&
-                 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)) {
+                 (SiS_Pr->SiS_LCDResInfo != Panel_1280x960)  &&
+                 (SiS_Pr->SiS_LCDResInfo != Panel_1600x1200)  &&
+                 ((romptr = GetLCDromptr(SiS_Pr)))) {
 
           /* Data for 1280x1024 wrong in 301B BIOS */
-           romptr = GetLCDromptr(SiS_Pr, HwInfo);
-          if(!romptr) return;
+          /* Data for 1600x1200 wrong in 301C BIOS */
           delay = ROMAddr[(romptr + index)];
 
         } else if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
@@ -10993,14 +10002,15 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
        } else {
 
            delay = SiS310_LCDDelayCompensation_301[myindex];
-          if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+          if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
              if(IS_SIS740) delay = 0x01;
-             else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
+             else if(SiS_Pr->ChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
              else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
           } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
              if(IS_SIS740) delay = 0x01;  /* ? */
              else          delay = 0x03;
-          } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+             if(SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) delay = 0x00; /* experience */
+          } else if(SiS_Pr->SiS_VBType & VB_SIS30xB) {
              if(IS_SIS740) delay = 0x01;
              else          delay = SiS310_LCDDelayCompensation_3xx301B[myindex];
           }
@@ -11013,14 +10023,14 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
        SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2D,0x0F,((delay << 4) & 0xf0));
        dochiptest = FALSE;
      }
-     
+
   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {                        /* ------------ TV */
 
      index = GetTVPtrIndex(SiS_Pr);
-     
-     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
 
-        if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
+
+        if(SiS_IsNotM650orLater(SiS_Pr)) {
 
            if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
              /* Always use the second pointer on 650; some BIOSes */
@@ -11062,7 +10072,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 
      } else if((SiS_Pr->SiS_UseROM) && (!(SiS_Pr->SiS_ROMNew))) {
 
-        romptr = GetTVromptr(SiS_Pr, HwInfo);
+        romptr = GetTVromptr(SiS_Pr);
        if(!romptr) return;
        delay = ROMAddr[romptr + index];
 
@@ -11073,7 +10083,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
      } else {
 
        delay = SiS310_TVDelayCompensation_301[index];
-        if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+        if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
           if(IS_SIS740) {
              delay = SiS310_TVDelayCompensation_740301B[index];
              /* LV: use 301 data? BIOS bug? */
@@ -11085,18 +10095,18 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 
      }
 
-     if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+     if(SiS_LCDAEnabled(SiS_Pr)) {
        delay &= 0x0f;
        dochiptest = FALSE;
      }
-    
+
   } else return;
 
   /* Write delay */
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && dochiptest) {
+     if(IS_SIS650 && (SiS_Pr->SiS_VBType & VB_SISLVDS) && dochiptest) {
 
         temp = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0xf0) >> 4;
         if(temp == 8) {                /* 1400x1050 BIOS (COMPAL) */
@@ -11134,11 +10144,10 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo)
 }
 
 static void
-SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-               USHORT ModeNo,USHORT ModeIdIndex)
+SetAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,temp1,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,temp1,romptr=0;
 
   if(SiS_Pr->SiS_TVMode & (TVSetYPbPr750p|TVSetYPbPr525p)) return;
 
@@ -11152,14 +10161,14 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   temp1 = temp;
 
   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
-     if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->ChipType >= SIS_661) {
         temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
         romptr = SISGETROMW(0x260);
-        if(HwInfo->jChipType >= SIS_760) {
+        if(SiS_Pr->ChipType >= SIS_760) {
           romptr = SISGETROMW(0x360);
        }
-     } else if(HwInfo->jChipType >= SIS_330) {
+     } else if(SiS_Pr->ChipType >= SIS_330) {
         romptr = SISGETROMW(0x192);
      } else {
         romptr = SISGETROMW(0x112);
@@ -11178,11 +10187,10 @@ SetAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-               USHORT ModeNo,USHORT ModeIdIndex)
+SetEdgeEnhance(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,temp1,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,temp1,romptr=0;
 
   temp = temp1 = GetTVPtrIndex(SiS_Pr) >> 1;   /* 0: NTSC/YPbPr, 1: PAL, 2: HiTV */
 
@@ -11192,14 +10200,14 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
      index = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
 
   if(SiS_Pr->SiS_UseROM && (!(SiS_Pr->SiS_ROMNew))) {
-     if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->ChipType >= SIS_661) {
         romptr = SISGETROMW(0x26c);
-        if(HwInfo->jChipType >= SIS_760) {
+        if(SiS_Pr->ChipType >= SIS_760) {
           romptr = SISGETROMW(0x36c);
        }
        temp1 = GetOEMTVPtr661(SiS_Pr);
         temp1 >>= 1;
-     } else if(HwInfo->jChipType >= SIS_330) {
+     } else if(SiS_Pr->ChipType >= SIS_330) {
         romptr = SISGETROMW(0x1a4);
      } else {
         romptr = SISGETROMW(0x124);
@@ -11217,10 +10225,9 @@ SetEdgeEnhance(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-           USHORT ModeNo,USHORT ModeIdIndex)
+SetYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
 {
-  USHORT index, temp, i, j;
+  unsigned short index, temp, i, j;
 
   if(ModeNo <= 0x13) {
      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
@@ -11235,7 +10242,7 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   else if(SiS_Pr->SiS_TVMode & TVSetPALN)    temp = 4;  /* PAL-N */
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) temp = 1;  /* HiVision uses PAL */
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
      for(i=0x35, j=0; i<=0x38; i++, j++) {
         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVYFilter2[temp][index][j]);
      }
@@ -11250,23 +10257,22 @@ SetYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-             USHORT ModeNo,USHORT ModeIdIndex)
+SetPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,i,j,resinfo,romptr=0;
-  ULONG  lindex;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,i,j,resinfo,romptr=0;
+  unsigned int  lindex;
 
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) return;
 
   /* NTSC-J data not in BIOS, and already set in SetGroup2 */
   if(SiS_Pr->SiS_TVMode & TVSetNTSCJ) return;
 
-  if((HwInfo->jChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
+  if((SiS_Pr->ChipType >= SIS_661) || SiS_Pr->SiS_ROMNew) {
      lindex = GetOEMTVPtr661_2_OLD(SiS_Pr) & 0xffff;
      lindex <<= 2;
      for(j=0, i=0x31; i<=0x34; i++, j++) {
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS661_TVPhase[lindex + j]);
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS_TVPhase[lindex + j]);
      }
      return;
   }
@@ -11286,17 +10292,17 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
    */
   if(SiS_Pr->SiS_UseROM) {
      romptr = SISGETROMW(0x116);
-     if(HwInfo->jChipType >= SIS_330) {
+     if(SiS_Pr->ChipType >= SIS_330) {
         romptr = SISGETROMW(0x196);
      }
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+     if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
         romptr = SISGETROMW(0x11c);
-       if(HwInfo->jChipType >= SIS_330) {
+       if(SiS_Pr->ChipType >= SIS_330) {
           romptr = SISGETROMW(0x19c);
        }
        if((SiS_Pr->SiS_VBInfo & SetInSlaveMode) && (!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode))) {
           romptr = SISGETROMW(0x116);
-          if(HwInfo->jChipType >= SIS_330) {
+          if(SiS_Pr->ChipType >= SIS_330) {
               romptr = SISGETROMW(0x196);
            }
        }
@@ -11311,7 +10317,7 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
      index = temp % 2;
      temp >>= 1;          /* 0:NTSC, 1:PAL, 2:HiTV */
      for(j=0, i=0x31; i<=0x34; i++, j++) {
-        if(!(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV))
+        if(!(SiS_Pr->SiS_VBType & VB_SIS30xBLV))
           SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr1[temp][index][j]);
         else if((!(SiS_Pr->SiS_VBInfo & SetInSlaveMode)) || (SiS_Pr->SiS_TVMode & TVSetTVSimuMode))
            SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS310_TVPhaseIncr2[temp][index][j]);
@@ -11320,7 +10326,7 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
      }
   }
 
-  if((SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
+  if((SiS_Pr->SiS_VBType & VB_SIS30xBLV) && (!(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision))) {
      if((!(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetYPbPr525p | TVSetYPbPr750p))) && (ModeNo > 0x13)) {
         if((resinfo == SIS_RI_640x480) ||
           (resinfo == SIS_RI_800x600)) {
@@ -11339,11 +10345,11 @@ SetPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
-                USHORT ModeIdIndex, USHORT RTI)
+SetDelayComp661(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                unsigned short ModeIdIndex, unsigned short RTI)
 {
-   USHORT delay = 0, romptr = 0, index, lcdpdcindex;
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+   unsigned short delay = 0, romptr = 0, index, lcdpdcindex;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
 
    if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToTV | SetCRT2ToLCD | SetCRT2ToLCDA | SetCRT2ToRAMDAC)))
       return;
@@ -11359,7 +10365,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
          if(SiS_Pr->UseCustomMode) {
            index = SiS_Pr->CSRClock;
          } else if(ModeNo > 0x13) {
-            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI,HwInfo);
+            index = SiS_GetVCLK2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RTI);
             index = SiS_Pr->SiS_VCLKData[index].CLOCK;
          }
         if(index < 25) index = 25;
@@ -11387,7 +10393,36 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
    else                      delay = (SiS_Pr->SiS_RefIndex[RTI].Ext_PDC >> 4);
    delay |= (delay << 8);
 
-   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+   if(SiS_Pr->ChipType >= XGI_20) {
+
+      delay = 0x0606;
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+
+        delay = 0x0404;
+         if(SiS_Pr->SiS_XGIROM) {
+            index = GetTVPtrIndex(SiS_Pr);
+            if((romptr = SISGETROMW(0x35e))) {
+               delay = (ROMAddr[romptr + index] & 0x0f) << 1;
+               delay |= (delay << 8);
+            }
+        }
+
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+           if(SiS_Pr->ChipType == XGI_40 && SiS_Pr->ChipRevision == 0x02) {
+              delay -= 0x0404;
+           }
+        }
+      }
+
+   } else if(SiS_Pr->ChipType >= SIS_340) {
+
+      delay = 0x0606;
+      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
+         delay = 0x0404;
+      }
+      /* TODO (eventually) */
+
+   } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
 
       /* 3. TV */
 
@@ -11406,7 +10441,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
       /* 4. LCD, LCDA (for new ROM only LV and non-Pass 1:1) */
 
       if( (SiS_Pr->SiS_LCDResInfo != Panel_Custom) &&
-          ((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) ) {
+          ((romptr = GetLCDStructPtr661_2(SiS_Pr))) ) {
 
         lcdpdcindex = (SiS_Pr->SiS_VBType & VB_UMC) ? 14 : 12;
 
@@ -11426,6 +10461,7 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
            case Panel_1280x768_2:delay = 0x0004; break;
            case Panel_1280x800:
            case Panel_1280x800_2:delay = 0x0004; break; /* Verified for 1280x800 */
+           case Panel_1280x854:  delay = 0x0004; break; /* FIXME */
            case Panel_1280x1024: delay = 0x1e04; break;
            case Panel_1400x1050: delay = 0x0004; break;
            case Panel_1600x1200: delay = 0x0400; break;
@@ -11469,10 +10505,10 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo,
 }
 
 static void
-SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, USHORT RTI)
+SetCRT2SyncDither661(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short RTI)
 {
-   USHORT infoflag;
-   UCHAR temp;
+   unsigned short infoflag;
+   unsigned char  temp;
 
    if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
 
@@ -11513,12 +10549,16 @@ SetCRT2SyncDither661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo, US
 }
 
 static void
-SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+SetPanelParms661(struct SiS_Private *SiS_Pr)
 {
-   UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-   USHORT romptr, temp1, temp2;
+   unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+   unsigned short romptr, temp1, temp2;
+
+   if(SiS_Pr->SiS_VBType & (VB_SISLVDS | VB_SIS30xC)) {
+      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x24,0x0f);
+   }
 
-   if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+   if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
       if(SiS_Pr->LVDSHL != -1) {
          SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,0xfc,SiS_Pr->LVDSHL);
       }
@@ -11526,8 +10566,8 @@ SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 
    if(SiS_Pr->SiS_ROMNew) {
 
-      if((romptr = GetLCDStructPtr661_2(SiS_Pr, HwInfo))) {
-         if(SiS_Pr->SiS_VBType & (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV)) {
+      if((romptr = GetLCDStructPtr661_2(SiS_Pr))) {
+         if(SiS_Pr->SiS_VBType & VB_SISLVDS) {
             temp1 = (ROMAddr[romptr] & 0x03) | 0x0c;
            temp2 = 0xfc;
            if(SiS_Pr->LVDSHL != -1) {
@@ -11546,48 +10586,47 @@ SetPanelParms661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 }
 
 static void
-SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                  USHORT ModeNo,USHORT ModeIdIndex,USHORT RRTI)
+SiS_OEM310Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RRTI)
 {
    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SISLVDS)) {
-      SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
+      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-         SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
-         SetPanelParms661(SiS_Pr,HwInfo);
+         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+         SetPanelParms661(SiS_Pr);
       }
    } else {
-      SetDelayComp(SiS_Pr,HwInfo,ModeNo);
+      SetDelayComp(SiS_Pr,ModeNo);
    }
 
    if((SiS_Pr->SiS_VBType & VB_SISVB) && (SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) {
-      SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-      SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-      SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+      SetAntiFlicker(SiS_Pr,ModeNo,ModeIdIndex);
+      SetPhaseIncr(SiS_Pr,ModeNo,ModeIdIndex);
+      SetYFilter(SiS_Pr,ModeNo,ModeIdIndex);
       if(SiS_Pr->SiS_VBType & VB_SIS301) {
-         SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+         SetEdgeEnhance(SiS_Pr,ModeNo,ModeIdIndex);
       }
    }
 }
 
 static void
-SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                  USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI)
+SiS_OEM661Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                       unsigned short ModeIdIndex, unsigned short RRTI)
 {
    if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-      SetDelayComp661(SiS_Pr,HwInfo,ModeNo,ModeIdIndex,RRTI);
+      SetDelayComp661(SiS_Pr, ModeNo, ModeIdIndex, RRTI);
 
       if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-         SetCRT2SyncDither661(SiS_Pr,HwInfo,ModeNo,RRTI);
-         SetPanelParms661(SiS_Pr,HwInfo);
+         SetCRT2SyncDither661(SiS_Pr, ModeNo, RRTI);
+         SetPanelParms661(SiS_Pr);
       }
 
       if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-         SetPhaseIncr(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-         SetYFilter(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
-         SetAntiFlicker(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+         SetPhaseIncr(SiS_Pr, ModeNo, ModeIdIndex);
+         SetYFilter(SiS_Pr, ModeNo, ModeIdIndex);
+         SetAntiFlicker(SiS_Pr, ModeNo, ModeIdIndex);
          if(SiS_Pr->SiS_VBType & VB_SIS301) {
-            SetEdgeEnhance(SiS_Pr,HwInfo,ModeNo,ModeIdIndex);
+            SetEdgeEnhance(SiS_Pr, ModeNo, ModeIdIndex);
          }
       }
    }
@@ -11601,13 +10640,12 @@ SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
  * pray that we have a backup...
  */
 static void
-SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                PSIS_HW_INFO HwInfo)
+SiS_FinalizeLCD(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  USHORT tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
-  USHORT resinfo,modeflag;
+  unsigned short tempcl,tempch,tempbl,tempbh,tempbx,tempax,temp;
+  unsigned short resinfo,modeflag;
 
-  if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) return;
+  if(!(SiS_Pr->SiS_VBType & VB_SISLVDS)) return;
   if(SiS_Pr->SiS_ROMNew) return;
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
@@ -11678,7 +10716,7 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
-       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+       if(SiS_Pr->SiS_VBType & VB_SISEMI) {
           SiS_SetReg(SiS_Pr->SiS_Part4Port,0x2a,0x00);
 #ifdef SET_EMI
           SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
@@ -11806,11 +10844,11 @@ SiS_FinalizeLCD(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
 #ifdef SIS300
 
 static void
-SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-               USHORT ModeNo,USHORT ModeIdIndex, USHORT RefTabIndex)
+SetOEMLCDData2(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex,
+               unsigned short RefTabIndex)
 {
-  USHORT crt2crtc=0, modeflag, myindex=0;
-  UCHAR  temp;
+  unsigned short crt2crtc=0, modeflag, myindex=0;
+  unsigned char  temp;
   int i;
 
   if(ModeNo <= 0x13) {
@@ -11849,21 +10887,21 @@ SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   }
 }
 
-static USHORT
-GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
+static unsigned short
+GetOEMLCDPtr(struct SiS_Private *SiS_Pr, int Flag)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT tempbx=0,romptr=0;
-  UCHAR customtable300[] = {
-       0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short tempbx=0,romptr=0;
+  static const unsigned char customtable300[] = {
+       0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
   };
-  UCHAR customtable630[] = {
-       0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+  static const unsigned char customtable630[] = {
+       0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
   };
 
-  if(HwInfo->jChipType == SIS_300) {
+  if(SiS_Pr->ChipType == SIS_300) {
 
     tempbx = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) & 0x0f;
     if(SiS_Pr->SiS_VBType & VB_SIS301) tempbx &= 0x07;
@@ -11912,11 +10950,10 @@ GetOEMLCDPtr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, int Flag)
 }
 
 static void
-SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-               USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMLCDDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,romptr=0;
 
   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom) return;
 
@@ -11927,22 +10964,22 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   }
 
   /* The Panel Compensation Delay should be set according to tables
-   * here. Unfortunately, various BIOS versions don't case about
+   * here. Unfortunately, various BIOS versions don't care about
    * a uniform way using eg. ROM byte 0x220, but use different
    * hard coded delays (0x04, 0x20, 0x18) in SetGroup1().
-   * Thus we don't set this if the user select a custom pdc or if
+   * Thus we don't set this if the user selected a custom pdc or if
    * we otherwise detected a valid pdc.
    */
   if(SiS_Pr->PDC != -1) return;
 
-  temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 0);
+  temp = GetOEMLCDPtr(SiS_Pr, 0);
 
   if(SiS_Pr->UseCustomMode)
      index = 0;
   else
      index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_LCDDelayIndex;
 
-  if(HwInfo->jChipType != SIS_300) {
+  if(SiS_Pr->ChipType != SIS_300) {
      if(romptr) {
        romptr += (temp * 2);
        romptr = SISGETROMW(romptr);
@@ -11986,12 +11023,11 @@ SetOEMLCDDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-              USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMLCDData(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
 #if 0  /* Unfinished; Data table missing */
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp;
 
   if((SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x237] & 0x01)) return;
@@ -11999,8 +11035,8 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
      /* No rom pointer in BIOS header! */
   }
 
-  temp = GetOEMLCDPtr(SiS_Pr,HwInfo, 1);
-  if(temp = 0xFFFF) return;
+  temp = GetOEMLCDPtr(SiS_Pr, 1);
+  if(temp == 0xFFFF) return;
 
   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex]._VB_LCDHIndex;
   for(i=0x14, j=0; i<=0x17; i++, j++) {
@@ -12018,10 +11054,10 @@ SetOEMLCDData(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 #endif
 }
 
-static USHORT
-GetOEMTVPtr(SiS_Private *SiS_Pr)
+static unsigned short
+GetOEMTVPtr(struct SiS_Private *SiS_Pr)
 {
-  USHORT index;
+  unsigned short index;
 
   index = 0;
   if(!(SiS_Pr->SiS_VBInfo & SetInSlaveMode))  index += 4;
@@ -12037,11 +11073,10 @@ GetOEMTVPtr(SiS_Private *SiS_Pr)
 }
 
 static void
-SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-              USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMTVDelay(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,romptr=0;
 
   if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
@@ -12070,11 +11105,10 @@ SetOEMTVDelay(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                  USHORT ModeNo, USHORT ModeIdIndex)
+SetOEMAntiFlicker(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,romptr=0;
 
   if(SiS_Pr->SiS_UseROM) {
      if(!(ROMAddr[0x238] & 0x01)) return;
@@ -12099,11 +11133,10 @@ SetOEMAntiFlicker(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMPhaseIncr(struct SiS_Private *SiS_Pr, unsigned short ModeNo,unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,i,j,temp,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,i,j,temp,romptr=0;
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) return;
 
@@ -12119,7 +11152,7 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 
   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVPhaseIndex;
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
      for(i=0x31, j=0; i<=0x34; i++, j++) {
         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Phase2[temp][index][j]);
      }
@@ -12140,11 +11173,10 @@ SetOEMPhaseIncr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 }
 
 static void
-SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-              USHORT ModeNo,USHORT ModeIdIndex)
+SetOEMYFilter(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex)
 {
-  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT index,temp,i,j,romptr=0;
+  unsigned char  *ROMAddr = SiS_Pr->VirtualRomBase;
+  unsigned short index,temp,i,j,romptr=0;
 
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSCART | SetCRT2ToHiVision | SetCRT2ToYPbPr525750)) return;
 
@@ -12162,7 +11194,7 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 
   index = SiS_Pr->SiS_VBModeIDTable[ModeIdIndex].VB_TVYFilterIndex;
 
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
+  if(SiS_Pr->SiS_VBType & VB_SIS30xBLV) {
       for(i=0x35, j=0; i<=0x38; i++, j++) {
                SiS_SetReg(SiS_Pr->SiS_Part2Port,i,SiS300_Filter2[temp][index][j]);
       }
@@ -12185,11 +11217,11 @@ SetOEMYFilter(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   }
 }
 
-static USHORT
-SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
+static unsigned short
+SiS_SearchVBModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo)
 {
-   USHORT ModeIdIndex;
-   UCHAR VGAINFO = SiS_Pr->SiS_VGAINFO;
+   unsigned short ModeIdIndex;
+   unsigned char  VGAINFO = SiS_Pr->SiS_VGAINFO;
 
    if(*ModeNo <= 5) *ModeNo |= 1;
 
@@ -12210,10 +11242,10 @@ SiS_SearchVBModeID(SiS_Private *SiS_Pr, USHORT *ModeNo)
 }
 
 static void
-SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                 USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTableIndex)
+SiS_OEM300Setting(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                 unsigned short RefTableIndex)
 {
-  USHORT OEMModeIdIndex=0;
+  unsigned short OEMModeIdIndex = 0;
 
   if(!SiS_Pr->UseCustomMode) {
      OEMModeIdIndex = SiS_SearchVBModeID(SiS_Pr,&ModeNo);
@@ -12221,18 +11253,18 @@ SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
   }
 
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-     SetOEMLCDDelay(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+     SetOEMLCDDelay(SiS_Pr, ModeNo, OEMModeIdIndex);
      if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-        SetOEMLCDData(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+        SetOEMLCDData(SiS_Pr, ModeNo, OEMModeIdIndex);
      }
   }
   if(SiS_Pr->UseCustomMode) return;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     SetOEMTVDelay(SiS_Pr, HwInfo, ModeNo,OEMModeIdIndex);
+     SetOEMTVDelay(SiS_Pr, ModeNo,OEMModeIdIndex);
      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-        SetOEMAntiFlicker(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
-       SetOEMPhaseIncr(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
-               SetOEMYFilter(SiS_Pr, HwInfo, ModeNo, OEMModeIdIndex);
+        SetOEMAntiFlicker(SiS_Pr, ModeNo, OEMModeIdIndex);
+       SetOEMPhaseIncr(SiS_Pr, ModeNo, OEMModeIdIndex);
+               SetOEMYFilter(SiS_Pr, ModeNo, OEMModeIdIndex);
      }
   }
 }
index f84eb54164a5d8fe4069231ebe77fe5b25012be1..f475b21a85cfa6f87161698a84ef8e65d4c98df4 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * Data and prototypes for init301.c
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-#ifndef  _INIT301_
-#define  _INIT301_
+#ifndef  _INIT301_H_
+#define  _INIT301_H_
 
 #include "osdef.h"
 #include "initdef.h"
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 #include "sis.h"
 #include "sis_regs.h"
 #endif
 
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
 #include "vgatypes.h"
 #include "vstruct.h"
 #ifdef SIS_CP
 #endif
 #include <linux/config.h>
 #include <linux/version.h>
-#include <asm/io.h>
 #include <linux/types.h>
+#include <asm/io.h>
+#include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <video/fbcon.h>
+#endif
+#include "sis.h"
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <linux/sisfb.h>
 #else
@@ -78,7 +83,7 @@
 #endif
 #endif
 
-static const UCHAR SiS_YPbPrTable[3][64] = {
+static const unsigned char SiS_YPbPrTable[3][64] = {
   {
     0x17,0x1d,0x03,0x09,0x05,0x06,0x0c,0x0c,
     0x94,0x49,0x01,0x0a,0x06,0x0d,0x04,0x0a,
@@ -90,17 +95,17 @@ static const UCHAR SiS_YPbPrTable[3][64] = {
     0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
   },
   {
-    0x1d,0x11,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
+    0x33,0x06,0x06,0x09,0x0b,0x0c,0x0c,0x0c,
     0x98,0x0a,0x01,0x0d,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4c /*0x4f*/,0x13,
+    0x0c,0x50,0xb2,0x9f,0x16,0x59,0x4f,0x13,
     0xad,0x11,0xad,0x1d,0x40,0x8a,0x3d,0xb8,
-    0x51,0x5e,0x60,0x57 /*0x49*/,0x7b /*0x7d*/,0x92,0x0f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4b,
+    0x51,0x5e,0x60,0x49,0x7d,0x92,0x0f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x4e,
     0x43,0x41,0x11,0x00,0xfc,0xff,0x32,0x00
   },
   {
-#if 1
+#if 0 /* OK, but sticks to left edge */
     0x13,0x1d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
     0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
@@ -110,20 +115,42 @@ static const UCHAR SiS_YPbPrTable[3][64] = {
     0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x27,
     0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
 #endif
-#if 0
-    0x2a,0x14,0xe8,0x09,0x09,0xed,0x0c,0x0c,  /* TEST (0.93) - BAD */
+#if 1 /* Perfect */
+    0x23,0x2d,0xe8,0x09,0x09,0xed,0x0c,0x0c,
     0x98,0x0a,0x01,0x0c,0x06,0x0d,0x04,0x0a,
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x3f,
-    0xed,0x50,0x70,0x9e,0x16,0x57,0x6c,0x13,
-    0x27,0x0b,0x27,0xfb,0x30,0x27,0x15,0xb0,
-    0x3b,0xdb,0x61,0x24,0x78,0x92,0x0f,0xff,
-    0xff,0xff,0xff,0xff,0xff,0xff,0x14,0x6f,
-    0x00,0x52,0xbb,0x00,0xd5,0xf7,0xa2,0x00
+    0xed,0x50,0x70,0x9f,0x16,0x59,0x60,0x13,
+    0x27,0x0b,0x27,0xfc,0x30,0x27,0x1c,0xb0,
+    0x4b,0x4b,0x6f,0x2f,0x63,0x92,0x0f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x73,
+    0x00,0x40,0x11,0x00,0xfc,0xff,0x32,0x00
 #endif
   }
 };
 
-static const UCHAR SiS_HiTVGroup3_1[] = {
+static const unsigned char SiS_TVPhase[] =
+{
+       0x21,0xED,0xBA,0x08,    /* 0x00 SiS_NTSCPhase */
+       0x2A,0x05,0xE3,0x00,    /* 0x01 SiS_PALPhase */
+       0x21,0xE4,0x2E,0x9B,    /* 0x02 SiS_PALMPhase */
+       0x21,0xF4,0x3E,0xBA,    /* 0x03 SiS_PALNPhase */
+       0x1E,0x8B,0xA2,0xA7,
+       0x1E,0x83,0x0A,0xE0,    /* 0x05 SiS_SpecialPhaseM */
+       0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,
+       0x21,0xF0,0x7B,0xD6,    /* 0x08 SiS_NTSCPhase2 */
+       0x2A,0x09,0x86,0xE9,    /* 0x09 SiS_PALPhase2 */
+       0x21,0xE6,0xEF,0xA4,    /* 0x0a SiS_PALMPhase2 */
+       0x21,0xF6,0x94,0x46,    /* 0x0b SiS_PALNPhase2 */
+       0x1E,0x8B,0xA2,0xA7,
+       0x1E,0x83,0x0A,0xE0,    /* 0x0d SiS_SpecialPhaseM */
+       0x00,0x00,0x00,0x00,
+       0x00,0x00,0x00,0x00,
+       0x1e,0x8c,0x5c,0x7a,    /* 0x10 SiS_SpecialPhase */
+       0x25,0xd4,0xfd,0x5e     /* 0x11 SiS_SpecialPhaseJ */
+};
+
+static const unsigned char SiS_HiTVGroup3_1[] = {
     0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x13,
     0xb1, 0x41, 0x62, 0x62, 0xff, 0xf4, 0x45, 0xa6,
     0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
@@ -134,7 +161,7 @@ static const UCHAR SiS_HiTVGroup3_1[] = {
     0x1a, 0x1f, 0x25, 0x2a, 0x4c, 0xaa, 0x01
 };
 
-static const UCHAR SiS_HiTVGroup3_2[] = {
+static const unsigned char SiS_HiTVGroup3_2[] = {
     0x00, 0x14, 0x15, 0x25, 0x55, 0x15, 0x0b, 0x7a,
     0x54, 0x41, 0xe7, 0xe7, 0xff, 0xf4, 0x45, 0xa6,
     0x25, 0x2f, 0x67, 0xf6, 0xbf, 0xff, 0x8e, 0x20,
@@ -147,7 +174,7 @@ static const UCHAR SiS_HiTVGroup3_2[] = {
 
 /* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
 
-static const UCHAR SiS_Part2CLVX_1[] = {
+static const unsigned char SiS_Part2CLVX_1[] = {
     0x00,0x00,
     0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
     0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
@@ -155,7 +182,7 @@ static const UCHAR SiS_Part2CLVX_1[] = {
     0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
 };
 
-static const UCHAR SiS_Part2CLVX_2[] = {
+static const unsigned char SiS_Part2CLVX_2[] = {
     0x00,0x00,
     0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
     0x7C,0x1D,0x09,0x7E,0x7C,0x1B,0x0B,0x7E,0x7C,0x19,0x0E,0x7D,0x7C,0x17,0x11,0x7C,
@@ -163,7 +190,7 @@ static const UCHAR SiS_Part2CLVX_2[] = {
     0x7E,0x09,0x1D,0x7C,0x7F,0x06,0x1F,0x7C,0x7F,0x04,0x20,0x7D,0x00,0x02,0x20,0x7E
 };
 
-static const UCHAR SiS_Part2CLVX_3[] = {  /* NTSC, 525i, 525p */
+static const unsigned char SiS_Part2CLVX_3[] = {  /* NTSC, 525i, 525p */
     0xE0,0x01,
     0x04,0x1A,0x04,0x7E,0x03,0x1A,0x06,0x7D,0x01,0x1A,0x08,0x7D,0x00,0x19,0x0A,0x7D,
     0x7F,0x19,0x0C,0x7C,0x7E,0x18,0x0E,0x7C,0x7E,0x17,0x10,0x7B,0x7D,0x15,0x12,0x7C,
@@ -182,7 +209,7 @@ static const UCHAR SiS_Part2CLVX_3[] = {  /* NTSC, 525i, 525p */
     0xFF,0xFF
 };
 
-static const UCHAR SiS_Part2CLVX_4[] = {   /* PAL */
+static const unsigned char SiS_Part2CLVX_4[] = {   /* PAL */
     0x58,0x02,
     0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
     0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
@@ -201,7 +228,7 @@ static const UCHAR SiS_Part2CLVX_4[] = {   /* PAL */
     0xFF,0xFF
 };
 
-static const UCHAR SiS_Part2CLVX_5[] = {   /* 750p */
+static const unsigned char SiS_Part2CLVX_5[] = {   /* 750p */
     0x00,0x03,
     0x05,0x19,0x05,0x7D,0x03,0x19,0x06,0x7E,0x02,0x19,0x08,0x7D,0x01,0x18,0x0A,0x7D,
     0x00,0x18,0x0C,0x7C,0x7F,0x17,0x0E,0x7C,0x7E,0x16,0x0F,0x7D,0x7E,0x14,0x11,0x7D,
@@ -210,7 +237,7 @@ static const UCHAR SiS_Part2CLVX_5[] = {   /* 750p */
     0xFF,0xFF
 };
 
-static const UCHAR SiS_Part2CLVX_6[] = {   /* 1080i */
+static const unsigned char SiS_Part2CLVX_6[] = {   /* 1080i */
     0x00,0x04,
     0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
     0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
@@ -221,7 +248,7 @@ static const UCHAR SiS_Part2CLVX_6[] = {   /* 1080i */
 
 #ifdef SIS315H
 /* 661 et al LCD data structure (2.03.00) */
-static const UCHAR SiS_LCDStruct661[] = {
+static const unsigned char SiS_LCDStruct661[] = {
     /* 1024x768 */
 /*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
     0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
@@ -249,11 +276,20 @@ static const UCHAR SiS_LCDStruct661[] = {
     /* 1680x1050 */
     0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
     0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06,
+    /* 1280x800_3 */
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0xAA,0x05,0x2E,0x03,0x30,0x00,0x50,
+    0x00,0x04,0x00,0x03,0x00,0x47,0xA9,0x10,0x00,0x00,0x00,0x00,0x07,
+    /* 800x600 */
+    0x01,0xC0,0x20,0x03,0x58,0x02,0x20,0x04,0x74,0x02,0x2A,0x00,0x80,
+    0x00,0x06,0x00,0x04,0x00,0x28,0x63,0x4B,0x00,0x00,0x00,0x00,0x00,
+    /* 1280x854 */
+    0x08,0xE0,0x00,0x05,0x56,0x03,0x80,0x06,0x5d,0x03,0x10,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x54,0x75,0x13,0x00,0x00,0x00,0x00,0x08
 };
 #endif
 
 #ifdef SIS300
-static UCHAR SiS300_TrumpionData[7][80] = {
+static unsigned char SiS300_TrumpionData[14][80] = {
   { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x0D,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
     0x20,0x03,0x0B,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x10,0x00,0x00,0x04,0x23,
     0x00,0x00,0x03,0x28,0x03,0x10,0x05,0x08,0x40,0x10,0x00,0x10,0x04,0x23,0x00,0x23,
@@ -288,119 +324,182 @@ static UCHAR SiS300_TrumpionData[7][80] = {
     0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
     0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
     0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
-    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 }
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x5B,0x01,0xBE,0x01,0x00 },
+  /* variant 2 */
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x15,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x18,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x44,0x03,0x28,0x06,0x08,0x40,0x18,0x00,0x18,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xA6,0x01,0xFF,0x03,0xFF,0x19,0x01,0x00,0x05,0x13,0x04,0x04,0x05,
+    0x04,0x0C,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x8A,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x72,0x00,0xD8,0x02,
+    0x84,0x03,0x16,0x00,0x90,0x01,0xC1,0x01,0x60,0x0C,0x30,0x1C,0x00,0x20,0x04,0x23,
+    0x00,0x01,0x03,0x53,0x03,0x28,0x06,0x08,0x40,0x1C,0x00,0x16,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xDA,0x01,0xFF,0x0F,0xF4,0x18,0x07,0x05,0x05,0x13,0x04,0x04,0x05,
+    0x01,0x0B,0x13,0x0A,0x02,0xB0,0x00,0x00,0x02,0xBA,0xF0,0x55,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x00,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0x7F,0x00,0x80,0x02,
+    0x20,0x03,0x16,0x00,0xE0,0x01,0x0D,0x02,0x60,0x0C,0x30,0x98,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x45,0x03,0x48,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0xF4,0x01,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x05,0x01,0x00,0x05,0x05,
+    0x04,0x0C,0x08,0x05,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x02,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xBF,0x00,0x20,0x03,
+    0x20,0x04,0x0D,0x00,0x58,0x02,0x71,0x02,0x80,0x0C,0x30,0x9A,0x00,0xFA,0x03,0x1D,
+    0x00,0x01,0x03,0x22,0x03,0x28,0x06,0x08,0x40,0x98,0x00,0x98,0x04,0x1D,0x00,0x1D,
+    0x03,0x11,0x60,0x39,0x03,0x40,0x05,0xF4,0x18,0x07,0x02,0x06,0x04,0x01,0x06,0x0B,
+    0x02,0x0A,0x20,0x19,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 },
+  { 0x02,0x0A,0x0A,0x01,0x04,0x01,0x00,0x03,0x11,0x00,0x0D,0x10,0xEF,0x00,0x00,0x04,
+    0x40,0x05,0x13,0x00,0x00,0x03,0x26,0x03,0x88,0x0C,0x30,0x90,0x00,0x00,0x04,0x23,
+    0x00,0x01,0x03,0x24,0x03,0x28,0x06,0x08,0x40,0x90,0x00,0x90,0x04,0x23,0x00,0x23,
+    0x03,0x11,0x60,0x40,0x05,0xFF,0x0F,0xF4,0x18,0x01,0x00,0x08,0x01,0x00,0x08,0x01,
+    0x00,0x08,0x01,0x01,0x02,0xB0,0x00,0x00,0x02,0xBA,0xEA,0x58,0x01,0xBE,0x01,0x00 }
 };
 #endif
 
-void   SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void   SiS_EnableCRT2(SiS_Private *SiS_Pr);
-USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-void   SiS_WaitRetrace1(SiS_Private *SiS_Pr);
-BOOLEAN        SiS_IsDualEdge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-BOOLEAN        SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void   SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-void   SiS_GetVBInfo(SiS_Private *SiS_Pr, USHORT ModeNo,
-               USHORT ModeIdIndex, PSIS_HW_INFO HwInfo,
-               int checkcrt2mode);
-void   SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void    SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-void   SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo);
-USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-USHORT SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex);
-void   SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-BOOLEAN        SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo);
-void   SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void   SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
+void           SiS_UnLockCRT2(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void           SiS_LockCRT2(struct SiS_Private *SiS_Pr);
+#endif
+void           SiS_EnableCRT2(struct SiS_Private *SiS_Pr);
+unsigned short SiS_GetRatePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+void           SiS_WaitRetrace1(struct SiS_Private *SiS_Pr);
+BOOLEAN                SiS_IsDualEdge(struct SiS_Private *SiS_Pr);
+BOOLEAN                SiS_IsVAMode(struct SiS_Private *SiS_Pr);
+void           SiS_GetVBInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                       unsigned short ModeIdIndex, int checkcrt2mode);
+void           SiS_SetYPbPr(struct SiS_Private *SiS_Pr);
+void           SiS_SetTVMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                       unsigned short ModeIdIndex);
+void           SiS_GetLCDResInfo(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+               unsigned short ModeIdIndex);
+unsigned short SiS_GetVCLK2Ptr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                       unsigned short RefreshRateTableIndex);
+unsigned short SiS_GetResInfo(struct SiS_Private *SiS_Pr,unsigned short ModeNo,unsigned short ModeIdIndex);
+void           SiS_DisableBridge(struct SiS_Private *SiS_Pr);
+#ifndef SIS_LINUX_KERNEL
+void           SiS_EnableBridge(struct SiS_Private *SiS_Pr);
+#endif
+BOOLEAN                SiS_SetCRT2Group(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+void           SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+void           SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
 
-void           SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT         SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax);
-void           SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT         SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax);
-void           SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
+void           SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+void           SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short tempax);
+#ifndef SIS_LINUX_KERNEL
+void           SiS_SetCH70xx(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+unsigned short SiS_GetCH70xx(struct SiS_Private *SiS_Pr, unsigned short tempax);
+#endif
+void           SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+                       unsigned char orval,unsigned short andval);
 #ifdef SIS315H
-static void    SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void    SiS_Chrontel701xOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void    SiS_ChrontelInitTVVSync(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-static void    SiS_ChrontelDoSomething1(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void           SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-void           SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
+static void    SiS_Chrontel701xOn(struct SiS_Private *SiS_Pr);
+static void    SiS_Chrontel701xOff(struct SiS_Private *SiS_Pr);
+static void    SiS_ChrontelInitTVVSync(struct SiS_Private *SiS_Pr);
+static void    SiS_ChrontelDoSomething1(struct SiS_Private *SiS_Pr);
+void           SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+void           SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
 #endif /* 315 */
 
 #ifdef SIS300
-#if 0
-static  void    SiS_SetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
-static  USHORT  SiS_GetTrumpReg(SiS_Private *SiS_Pr, USHORT tempbx);
-#endif
-static  BOOLEAN        SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
+static  BOOLEAN        SiS_SetTrumpionBlock(struct SiS_Private *SiS_Pr, unsigned char *dataptr);
+void           SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
 #endif
 
-void    SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-USHORT  SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-USHORT  SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
-                     USHORT adaptnum, USHORT DDCdatatype, UCHAR *buffer);
-#ifdef LINUX_XF86
-USHORT  SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-USHORT  SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-#endif
+void           SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+unsigned short SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+unsigned short SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+                       unsigned short adaptnum, unsigned short DDCdatatype,
+                       unsigned char *buffer, unsigned int VBFlags2);
 
-static void            SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
-static USHORT          SiS_SetStart(SiS_Private *SiS_Pr);
-static USHORT          SiS_SetStop(SiS_Private *SiS_Pr);
-static USHORT          SiS_SetSCLKLow(SiS_Private *SiS_Pr);
-static USHORT          SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
-static USHORT          SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-static USHORT          SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-static USHORT          SiS_CheckACK(SiS_Private *SiS_Pr);
-static USHORT          SiS_InitDDCRegs(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
-                        USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
-static USHORT          SiS_WriteDABDDC(SiS_Private *SiS_Pr);
-static USHORT          SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
-static USHORT          SiS_PrepareDDC(SiS_Private *SiS_Pr);
-static void            SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
-static USHORT          SiS_DoProbeDDC(SiS_Private *SiS_Pr);
-static USHORT          SiS_ProbeDDC(SiS_Private *SiS_Pr);
-static USHORT          SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, UCHAR *buffer);
+#ifdef SIS_XORG_XF86
+unsigned short         SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+                               int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+                               BOOLEAN checkcr32, unsigned int VBFlags2);
+unsigned short         SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+unsigned short         SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+                               unsigned char *buffer);
+#else
+static unsigned short  SiS_InitDDCRegs(struct SiS_Private *SiS_Pr, unsigned int VBFlags,
+                               int VGAEngine, unsigned short adaptnum, unsigned short DDCdatatype,
+                               BOOLEAN checkcr32, unsigned int VBFlags2);
+static unsigned short  SiS_ProbeDDC(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_ReadDDC(struct SiS_Private *SiS_Pr, unsigned short DDCdatatype,
+                               unsigned char *buffer);
+#endif
+static void            SiS_SetSwitchDDC2(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_SetStart(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_SetStop(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_SetSCLKLow(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_SetSCLKHigh(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_ReadDDC2Data(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_WriteDDC2Data(struct SiS_Private *SiS_Pr, unsigned short tempax);
+static unsigned short  SiS_CheckACK(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_WriteDABDDC(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_PrepareReadDDC(struct SiS_Private *SiS_Pr);
+static unsigned short  SiS_PrepareDDC(struct SiS_Private *SiS_Pr);
+static void            SiS_SendACK(struct SiS_Private *SiS_Pr, unsigned short yesno);
+static unsigned short  SiS_DoProbeDDC(struct SiS_Private *SiS_Pr);
 
+#ifdef SIS300
+static void            SiS_OEM300Setting(struct SiS_Private *SiS_Pr,
+                               unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefTabindex);
+static void            SetOEMLCDData2(struct SiS_Private *SiS_Pr,
+                               unsigned short ModeNo, unsigned short ModeIdIndex,unsigned short RefTableIndex);
+#endif
 #ifdef SIS315H
-static void            SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                        USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-static void            SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                        USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-static void            SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
+static void            SiS_OEM310Setting(struct SiS_Private *SiS_Pr,
+                               unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void            SiS_OEM661Setting(struct SiS_Private *SiS_Pr,
+                               unsigned short ModeNo,unsigned short ModeIdIndex, unsigned short RRTI);
+static void            SiS_FinalizeLCD(struct SiS_Private *, unsigned short, unsigned short);
 #endif
+
+extern void            SiS_SetReg(SISIOADDRESS, unsigned short, unsigned short);
+extern void            SiS_SetRegByte(SISIOADDRESS, unsigned short);
+extern void            SiS_SetRegShort(SISIOADDRESS, unsigned short);
+extern void            SiS_SetRegLong(SISIOADDRESS, unsigned int);
+extern unsigned char   SiS_GetReg(SISIOADDRESS, unsigned short);
+extern unsigned char   SiS_GetRegByte(SISIOADDRESS);
+extern unsigned short  SiS_GetRegShort(SISIOADDRESS);
+extern unsigned int    SiS_GetRegLong(SISIOADDRESS);
+extern void            SiS_SetRegANDOR(SISIOADDRESS, unsigned short, unsigned short, unsigned short);
+extern void            SiS_SetRegOR(SISIOADDRESS, unsigned short, unsigned short);
+extern void            SiS_SetRegAND(SISIOADDRESS, unsigned short, unsigned short);
+extern void            SiS_DisplayOff(struct SiS_Private *SiS_Pr);
+extern void            SiS_DisplayOn(struct SiS_Private *SiS_Pr);
+extern BOOLEAN         SiS_SearchModeID(struct SiS_Private *, unsigned short *, unsigned short *);
+extern unsigned short  SiS_GetModeFlag(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern unsigned short  SiS_GetModePtr(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short  SiS_GetColorDepth(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex);
+extern unsigned short  SiS_GetOffset(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned short ModeIdIndex,
+                               unsigned short RefreshRateTableIndex);
+extern void            SiS_LoadDAC(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern void            SiS_CalcLCDACRT1Timing(struct SiS_Private *SiS_Pr, unsigned short ModeNo,
+                               unsigned short ModeIdIndex);
+extern void            SiS_CalcCRRegisters(struct SiS_Private *SiS_Pr, int depth);
+extern unsigned short  SiS_GetRefCRTVCLK(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
+extern unsigned short  SiS_GetRefCRT1CRTC(struct SiS_Private *SiS_Pr, unsigned short Index, int UseWide);
 #ifdef SIS300
-static void            SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                        USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
-static void            SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                       USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+extern void            SiS_GetFIFOThresholdIndex300(struct SiS_Private *SiS_Pr, unsigned short *tempbx,
+                               unsigned short *tempcl);
+extern unsigned short  SiS_GetFIFOThresholdB300(unsigned short tempbx, unsigned short tempcl);
+extern unsigned short  SiS_GetLatencyFactor630(struct SiS_Private *SiS_Pr, unsigned short index);
+#ifdef SIS_LINUX_KERNEL
+extern unsigned int    sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+extern unsigned int    sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
 #endif
-
-extern void     SiS_SetReg(SISIOADDRESS, USHORT, USHORT);
-extern void     SiS_SetRegByte(SISIOADDRESS, USHORT);
-extern void     SiS_SetRegShort(SISIOADDRESS, USHORT);
-extern void     SiS_SetRegLong(SISIOADDRESS, ULONG);
-extern UCHAR    SiS_GetReg(SISIOADDRESS, USHORT);
-extern UCHAR    SiS_GetRegByte(SISIOADDRESS);
-extern USHORT   SiS_GetRegShort(SISIOADDRESS);
-extern ULONG    SiS_GetRegLong(SISIOADDRESS);
-extern void     SiS_SetRegANDOR(SISIOADDRESS, USHORT, USHORT, USHORT);
-extern void     SiS_SetRegOR(SISIOADDRESS, USHORT, USHORT);
-extern void     SiS_SetRegAND(SISIOADDRESS, USHORT, USHORT);
-extern void     SiS_DisplayOff(SiS_Private *SiS_Pr);
-extern void     SiS_DisplayOn(SiS_Private *SiS_Pr);
-extern BOOLEAN  SiS_SearchModeID(SiS_Private *, USHORT *, USHORT *);
-extern UCHAR    SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT   SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-extern USHORT   SiS_GetOffset(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
-                       USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo);
-extern void     SiS_LoadDAC(SiS_Private *SiS_Pr, PSIS_HW_INFO, USHORT ModeNo,
-                        USHORT ModeIdIndex);
-extern void    SiS_CalcLCDACRT1Timing(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex);
-#ifdef LINUX_XF86
-extern void     SiS_MakeClockRegs(ScrnInfoPtr pScrn, int clock, UCHAR *p2b, UCHAR *p2c);
-extern int     SiS_FindPanelFromDB(SISPtr pSiS, USHORT panelvendor, USHORT panelproduct,
-                       int *maxx, int *maxy, int *prefx, int *prefy);
 #endif
 
 #endif
index 55a82d6dc4cfddc2a2dbf3fa347bb3d3b8ce44f4..264b55a5947b87bb8104ef259ec6e67ad1656e1e 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * Global definitions for init.c and init301.c
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
 #ifndef _INITDEF_
 #define _INITDEF_
 
-#define IS_SIS330              (HwInfo->jChipType == SIS_330)
-#define IS_SIS550              (HwInfo->jChipType == SIS_550)
-#define IS_SIS650              (HwInfo->jChipType == SIS_650)  /* All versions, incl 651, M65x */
-#define IS_SIS740              (HwInfo->jChipType == SIS_740)
+#define IS_SIS330              (SiS_Pr->ChipType == SIS_330)
+#define IS_SIS550              (SiS_Pr->ChipType == SIS_550)
+#define IS_SIS650              (SiS_Pr->ChipType == SIS_650)  /* All versions, incl 651, M65x */
+#define IS_SIS740              (SiS_Pr->ChipType == SIS_740)
 #define IS_SIS651              (SiS_Pr->SiS_SysFlags & (SF_Is651 | SF_Is652))
 #define IS_SISM650             (SiS_Pr->SiS_SysFlags & (SF_IsM650 | SF_IsM652 | SF_IsM653))
 #define IS_SIS65x               (IS_SIS651 || IS_SISM650)       /* Only special versions of 65x */
-#define IS_SIS661              (HwInfo->jChipType == SIS_661)
-#define IS_SIS741              (HwInfo->jChipType == SIS_741)
-#define IS_SIS660              (HwInfo->jChipType == SIS_660)
-#define IS_SIS760              (HwInfo->jChipType == SIS_760)
-#define IS_SIS661741660760     (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760)
-#define IS_SIS650740            ((HwInfo->jChipType >= SIS_650) && (HwInfo->jChipType < SIS_330))
+#define IS_SIS661              (SiS_Pr->ChipType == SIS_661)
+#define IS_SIS741              (SiS_Pr->ChipType == SIS_741)
+#define IS_SIS660              (SiS_Pr->ChipType == SIS_660)
+#define IS_SIS760              (SiS_Pr->ChipType == SIS_760)
+#define IS_SIS761              (SiS_Pr->ChipType == SIS_761)
+#define IS_SIS661741660760     (IS_SIS661 || IS_SIS741 || IS_SIS660 || IS_SIS760 || IS_SIS761)
+#define IS_SIS650740            ((SiS_Pr->ChipType >= SIS_650) && (SiS_Pr->ChipType < SIS_330))
 #define IS_SIS550650740         (IS_SIS550 || IS_SIS650740)
 #define IS_SIS650740660         (IS_SIS650 || IS_SIS740 || IS_SIS661741660760)
 #define IS_SIS550650740660      (IS_SIS550 || IS_SIS650740660)
 #define SISGETROMW(x)          (ROMAddr[(x)] | (ROMAddr[(x)+1] << 8))
 
 /* SiS_VBType */
-#define VB_SIS301              0x0001
-#define VB_SIS301B             0x0002
-#define VB_SIS302B             0x0004
-#define VB_SIS301LV            0x0008
-#define VB_SIS302LV            0x0010
+#define VB_SIS301              0x0001
+#define VB_SIS301B             0x0002
+#define VB_SIS302B             0x0004
+#define VB_SIS301LV            0x0008
+#define VB_SIS302LV            0x0010
 #define VB_SIS302ELV           0x0020
-#define VB_SIS301C              0x0040
+#define VB_SIS301C             0x0040
+#define VB_SIS307T             0x0080
+#define VB_SIS307LV            0x0100
 #define VB_UMC                 0x4000
 #define VB_NoLCD               0x8000
-#define VB_SIS301BLV302BLV      (VB_SIS301B|VB_SIS301C|VB_SIS302B|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SIS301B302B          (VB_SIS301B|VB_SIS301C|VB_SIS302B)
-#define VB_SIS301LV302LV        (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISVB               (VB_SIS301 | VB_SIS301BLV302BLV)
-#define VB_SISTMDS             (VB_SIS301 | VB_SIS301B302B)
-#define VB_SISLVDS             VB_SIS301LV302LV
-#define VB_SISLCDA             (VB_SIS302B|VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISYPBPR            (VB_SIS301C|VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
-#define VB_SISHIVISION         (VB_SIS301|VB_SIS301B|VB_SIS302B)
+#define VB_SIS30xB             (VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SIS30xC             (VB_SIS301C | VB_SIS307T)
+#define VB_SISTMDS             (VB_SIS301 | VB_SIS301B | VB_SIS301C | VB_SIS302B | VB_SIS307T)
+#define VB_SISLVDS             (VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SIS30xBLV           (VB_SIS30xB | VB_SISLVDS)
+#define VB_SIS30xCLV           (VB_SIS30xC | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISVB               (VB_SIS301 | VB_SIS30xBLV)
+#define VB_SISLCDA             (VB_SIS302B | VB_SIS301C  | VB_SIS307T  | VB_SISLVDS)
+#define VB_SISTMDSLCDA         (VB_SIS301C | VB_SIS307T)
+#define VB_SISPART4SCALER      (VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISHIVISION         (VB_SIS301 | VB_SIS301B | VB_SIS302B)
+#define VB_SISYPBPR            (VB_SIS301C | VB_SIS307T  | VB_SIS301LV | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISTAP4SCALER       (VB_SIS301C | VB_SIS307T | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPART4OVERFLOW    (VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPWD              (VB_SIS301C | VB_SIS307T | VB_SISLVDS)
+#define VB_SISEMI              (VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISPOWER            (VB_SIS301C | VB_SIS307T | VB_SIS302LV | VB_SIS302ELV | VB_SIS307LV)
+#define VB_SISDUALLINK         (VB_SIS302LV | VB_SIS302ELV | VB_SIS307T | VB_SIS307LV)
+#define VB_SISVGA2             VB_SISTMDS
+#define VB_SISRAMDAC202                (VB_SIS301C | VB_SIS307T)
 
 /* VBInfo */
 #define SetSimuScanMode         0x0001   /* CR 30 */
 #define SupportRAMDAC2_202      0x0400  /* C             (<= 202Mhz) */
 #define InterlaceMode           0x0080
 #define SyncPP                  0x0000
+#define HaveWideTiming         0x2000  /* Have specific wide- and non-wide timing */
 #define SyncPN                  0x4000
 #define SyncNP                  0x8000
 #define SyncNN                  0xc000
 #define TVSetTVSimuMode                0x0200 /* new 0x200, prev. 0x800 */
 #define TVRPLLDIV2XO           0x0400 /* prev 0x1000 */
 #define TVSetNTSC1024          0x0800 /* new 0x100, prev. 0x2000 */
+#define TVSet525p1024          0x1000 /* TW */
 #define TVAspect43             0x2000
 #define TVAspect169            0x4000
 #define TVAspect43LB           0x8000
 #define SF_IsM661              0x0020
 #define SF_IsM741              0x0040
 #define SF_IsM760              0x0080
-#define SF_760LFB              0x8000  /* 760: We have LFB */
+#define SF_760UMA              0x4000  /* 76x: We have UMA */
+#define SF_760LFB              0x8000  /* 76x: We have LFB */
 
 /* CR32 (Newer 630, and 315 series)
 
 #define TVOverScanShift         4
 
 /* CR35 (661 series only)
-
    [0]    1 = PAL, 0 = NTSC
    [1]    1 = NTSC-J (if D0 = 0)
    [2]    1 = PALM (if D0 = 1)
    [3]    1 = PALN (if D0 = 1)
    [4]    1 = Overscan (Chrontel only)
    [7:5]  (only if D2 in CR38 is set)
-          000  525i
-         001  525p
+         000  525i
+         001  525p
          010  750p
          011  1080i (or HiVision on 301, 301B)
-
-   These bits are being translated to TVMode flag.
-
 */
 
-/*
-   CR37
-
+/* CR37
    [0]   Set 24/18 bit (0/1) RGB to LVDS/TMDS transmitter (set by BIOS)
    [3:1] External chip
          300 series:
            010   LVDS
            011   LVDS + Chrontel 7019
          660 series [2:1] only:
-            reserved (now in CR38)
+            reserved (chip type now in CR38)
          All other combinations reserved
    [3]    661 only: Pass 1:1 data
    [4]    LVDS: 0: Panel Link expands / 1: Panel Link does not expand
 #define Enable302LV_DualLink    0x04   /* 302LV only; enable dual link */
 
 /* CR39 (661 and later)
+   D[7]   LVDS (SiS or third party)
    D[1:0] YPbPr Aspect Ratio
           00 4:3 letterbox
          01 4:3
         0101 Set Contrast event
         0110 Set Mute event
         0111 Set Volume Up/Down event
-   [4]   Enable Backlight Control by BIOS/driver 
+   [4]   Enable Backlight Control by BIOS/driver
          (set by driver; set means that the BIOS should
         not touch the backlight registers because eg.
         the driver already switched off the backlight)
    [7]   TV UnderScan/OverScan (set by BIOS)
 */
 
+/* CR7C - 661 and later
+   [7]   DualEdge enabled (or: to be enabled)
+   [6]   CRT2 = TV/LCD/VGA enabled (or: to be enabled)
+   [5]   Init done (set at end of SiS_Init)
+   {4]   LVDS LCD capabilities
+   [3]   LVDS LCD capabilities
+   [2]   LVDS LCD capabilities (PWD)
+   [1]   LVDS LCD capabilities (PWD)
+   [0]   LVDS=1, TMDS=0 (SiS or third party)
+*/
+
+/* CR7E - 661 and later
+   VBType:
+   [7] LVDS (third party)
+   [3] 301C
+   [2] 302LV
+   [1] 301LV
+   [0] 301B
+*/
+
 /* LCDResInfo */
 #define Panel300_800x600        0x01   /* CR36 */
 #define Panel300_1024x768       0x02
 #define Panel300_1024x600       0x06
 #define Panel300_1152x768       0x07
 #define Panel300_1280x768       0x0a
-#define Panel300_320x480        0x0e   /* fstn - This is fake, can be any */
 #define Panel300_Custom                0x0f
 #define Panel300_Barco1366      0x10
 
 #define Panel310_1400x1050      0x09
 #define Panel310_1280x768       0x0a
 #define Panel310_1600x1200      0x0b
-#define Panel310_640x480_2      0x0c
-#define Panel310_640x480_3      0x0d
-#define Panel310_320x480        0x0e    /* fstn - TW: This is fake, can be any */
+#define Panel310_320x240_2      0x0c    /* xSTN */
+#define Panel310_320x240_3      0x0d    /* xSTN */
+#define Panel310_320x240_1      0x0e    /* xSTN - This is fake, can be any */
 #define Panel310_Custom                0x0f
 
 #define Panel661_800x600        0x01
 #define Panel661_1024x600       0x05
 #define Panel661_1152x864       0x06
 #define Panel661_1280x960       0x07
-#define Panel661_1152x768       0x08
+#define Panel661_1280x854       0x08
 #define Panel661_1400x1050      0x09
 #define Panel661_1280x768       0x0a
 #define Panel661_1600x1200      0x0b
 #define Panel_1680x1050         0x0d    /* 661etc  */
 #define Panel_1280x720         0x0e    /* 661etc  */
 #define Panel_Custom           0x0f    /* MUST BE 0x0f (for DVI DDC detection) */
-#define Panel_320x480           0x10    /* SiS 550 fstn - TW: This is fake, can be any */
+#define Panel_320x240_1         0x10    /* SiS 550 xSTN */
 #define Panel_Barco1366         0x11
 #define Panel_848x480          0x12
-#define Panel_640x480_2                0x13    /* SiS 550 */
-#define Panel_640x480_3                0x14    /* SiS 550 */
+#define Panel_320x240_2                0x13    /* SiS 550 xSTN */
+#define Panel_320x240_3                0x14    /* SiS 550 xSTN */
 #define Panel_1280x768_2        0x15   /* 30xLV */
 #define Panel_1280x768_3        0x16    /* (unused) */
 #define Panel_1280x800_2       0x17    /* 30xLV */
+#define Panel_856x480          0x18
+#define Panel_1280x854         0x19    /* 661etc */
 
 /* Index in ModeResInfo table */
 #define SIS_RI_320x200    0
 #define SIS_RI_1920x1080 31
 #define SIS_RI_960x540   32
 #define SIS_RI_960x600   33
+#define SIS_RI_1280x854  34
 
 /* CR5F */
 #define IsM650                  0x80
 #define VCLK100_300             0x43   /* Index in VCLKData table (300) */
 #define VCLK34_300              0x3d   /* Index in VCLKData table (300) */
 #define VCLK_CUSTOM_300                0x47
-#define VCLK65_315              0x0b   /* Index in (VB)VCLKData table (315) */
-#define VCLK108_2_315           0x19   /* Index in (VB)VCLKData table (315) */
-#define VCLK81_315             0x5b   /* Index in (VB)VCLKData table (315) */
-#define VCLK162_315             0x5e   /* Index in (VB)VCLKData table (315) */
-#define VCLK108_3_315           0x45   /* Index in VBVCLKData table (315) */
-#define VCLK100_315             0x46   /* Index in VBVCLKData table (315) */
+
+#define VCLK65_315              0x0b   /* Indices in (VB)VCLKData table (315) */
+#define VCLK108_2_315           0x19
+#define VCLK81_315             0x5b
+#define VCLK162_315             0x5e
+#define VCLK108_3_315           0x45
+#define VCLK100_315             0x46
 #define VCLK34_315              0x55
 #define VCLK68_315             0x0d
-#define VCLK_1280x800_315_2    0x5c   /* Index in VBVCLKData table (315) */
-#define VCLK121_315            0x5d   /* Index in VBVCLKData table (315) */
+#define VCLK_1280x800_315_2    0x5c
+#define VCLK121_315            0x5d
+#define VCLK130_315            0x72
 #define VCLK_1280x720          0x5f
 #define VCLK_1280x768_2                0x60
 #define VCLK_1280x768_3                0x61   /* (unused?) */
 #define VCLK_1152x864          0x64
 #define VCLK_1360x768          0x58
 #define VCLK_1280x800_315      0x6c
+#define VCLK_1280x854          0x76
 
 #define TVCLKBASE_300          0x21   /* Indices on TV clocks in VCLKData table (300) */
 #define TVCLKBASE_315          0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
new file mode 100644 (file)
index 0000000..cc856d9
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * SiS 300/540/630[S]/730[S]
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX]
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
+ *
+ * Linux kernel specific extensions to init.c/init301.c
+ *
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
+ *
+ * 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 named License,
+ * or 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
+ *
+ * Author:     Thomas Winischhofer <thomas@winischhofer.net>
+ */
+
+#include "osdef.h"
+#include "initdef.h"
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+int            sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+                       unsigned char modeno, unsigned char rateindex);
+int            sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+                       unsigned char rateindex, struct fb_var_screeninfo *var);
+#endif
+BOOLEAN                sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+                       int *htotal, int *vtotal, unsigned char rateindex);
+
+extern BOOLEAN SiSInitPtr(struct SiS_Private *SiS_Pr);
+extern BOOLEAN SiS_SearchModeID(struct SiS_Private *SiS_Pr, unsigned short *ModeNo,
+                       unsigned short *ModeIdIndex);
+extern void    SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata,
+                       int xres, int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+int
+sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
+                       unsigned char rateindex)
+{
+    unsigned short ModeNo = modeno;
+    unsigned short ModeIdIndex = 0, ClockIndex = 0;
+    unsigned short RRTI = 0;
+    int Clock;
+
+    if(!SiSInitPtr(SiS_Pr)) return 65000;
+
+    if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+    switch(ModeNo) {
+    case 0x5a: ModeNo = 0x50; break;
+    case 0x5b: ModeNo = 0x56;
+    }
+#endif
+
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {;
+       printk(KERN_ERR "Could not find mode %x\n", ModeNo);
+       return 65000;
+    }
+
+    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+       if(SiS_Pr->SiS_UseWide == 1) {
+         /* Wide screen: Ignore rateindex */
+         ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_WIDE;
+       } else {
+         RRTI += rateindex;
+         ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK_NORM;
+       }
+    } else {
+       RRTI += rateindex;
+       ClockIndex = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRTVCLK;
+    }
+
+    Clock = SiS_Pr->SiS_VCLKData[ClockIndex].CLOCK * 1000;
+
+    return Clock;
+}
+
+int
+sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+                       unsigned char rateindex, struct fb_var_screeninfo *var)
+{
+    unsigned short ModeNo = modeno;
+    unsigned short ModeIdIndex = 0, index = 0, RRTI = 0;
+    int            j;
+
+    if(!SiSInitPtr(SiS_Pr)) return 0;
+
+    if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+    switch(ModeNo) {
+       case 0x5a: ModeNo = 0x50; break;
+       case 0x5b: ModeNo = 0x56;
+    }
+#endif
+
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return 0;
+
+    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+       if(SiS_Pr->SiS_UseWide == 1) {
+         /* Wide screen: Ignore rateindex */
+         index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+       } else {
+         RRTI += rateindex;
+         index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+       }
+    } else {
+       RRTI += rateindex;
+       index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+    }
+
+    SiS_Generic_ConvertCRData(SiS_Pr,
+                       (unsigned char *)&SiS_Pr->SiS_CRT1Table[index].CR[0],
+                       SiS_Pr->SiS_RefIndex[RRTI].XRes,
+                       SiS_Pr->SiS_RefIndex[RRTI].YRes,
+                       var, FALSE);
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x8000)
+       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+    else
+       var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x4000)
+       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+    else
+       var->sync |= FB_SYNC_HOR_HIGH_ACT;
+
+    var->vmode = FB_VMODE_NONINTERLACED;
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & 0x0080)
+       var->vmode = FB_VMODE_INTERLACED;
+    else {
+       j = 0;
+       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+         if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
+                         SiS_Pr->SiS_RefIndex[RRTI].ModeID) {
+             if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
+                 var->vmode = FB_VMODE_DOUBLE;
+             }
+             break;
+         }
+         j++;
+       }
+    }
+
+    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+#if 0  /* Do this? */
+       var->upper_margin <<= 1;
+       var->lower_margin <<= 1;
+       var->vsync_len <<= 1;
+#endif
+    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       var->upper_margin >>= 1;
+       var->lower_margin >>= 1;
+       var->vsync_len >>= 1;
+    }
+
+    return 1;
+}
+#endif /* Linux >= 2.5 */
+
+BOOLEAN
+sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno, int *htotal,
+                       int *vtotal, unsigned char rateindex)
+{
+    unsigned short ModeNo = modeno;
+    unsigned short ModeIdIndex = 0, CRT1Index = 0;
+    unsigned short RRTI = 0;
+    unsigned char  sr_data, cr_data, cr_data2;
+
+    if(!SiSInitPtr(SiS_Pr)) return FALSE;
+
+    if(rateindex > 0) rateindex--;
+
+#ifdef SIS315H
+    switch(ModeNo) {
+       case 0x5a: ModeNo = 0x50; break;
+       case 0x5b: ModeNo = 0x56;
+    }
+#endif
+
+    if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) return FALSE;
+
+    RRTI = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].REFindex;
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & HaveWideTiming) {
+       if(SiS_Pr->SiS_UseWide == 1) {
+         /* Wide screen: Ignore rateindex */
+         CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_WIDE;
+       } else {
+         RRTI += rateindex;
+         CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC_NORM;
+       }
+    } else {
+       RRTI += rateindex;
+       CRT1Index = SiS_Pr->SiS_RefIndex[RRTI].Ext_CRT1CRTC;
+    }
+
+    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[0];
+    *htotal = (((cr_data & 0xff) | ((unsigned short) (sr_data & 0x03) << 8)) + 5) * 8;
+
+    sr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+    cr_data = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[6];
+    cr_data2 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+    *vtotal = ((cr_data & 0xFF) |
+              ((unsigned short)(cr_data2 & 0x01) <<  8) |
+              ((unsigned short)(cr_data2 & 0x20) <<  4) |
+              ((unsigned short)(sr_data  & 0x01) << 10)) + 2;
+
+    if(SiS_Pr->SiS_RefIndex[RRTI].Ext_InfoFlag & InterlaceMode)
+       *vtotal *= 2;
+
+    return TRUE;
+}
+
+
+
index b1358b750f53c3b0de9a8c79e4e0636044c07d46..b73f2684014345e1f0cd434058b91593adb79fa7 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * OEM Data for 300 series
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
@@ -50,7 +50,7 @@
  *
  */
 
-static const UCHAR SiS300_OEMTVDelay301[8][4] =
+static const unsigned char SiS300_OEMTVDelay301[8][4] =
 {
        {0x08,0x08,0x08,0x08},
        {0x08,0x08,0x08,0x08},
@@ -62,7 +62,7 @@ static const UCHAR SiS300_OEMTVDelay301[8][4] =
        {0x20,0x20,0x20,0x20}
 };
 
-static const UCHAR SiS300_OEMTVDelayLVDS[8][4] =
+static const unsigned char SiS300_OEMTVDelayLVDS[8][4] =
 {
        {0x20,0x20,0x20,0x20},
        {0x20,0x20,0x20,0x20},
@@ -74,7 +74,7 @@ static const UCHAR SiS300_OEMTVDelayLVDS[8][4] =
        {0x20,0x20,0x20,0x20}
 };
 
-static const UCHAR SiS300_OEMTVFlicker[8][4] =
+static const unsigned char SiS300_OEMTVFlicker[8][4] =
 {
        {0x00,0x00,0x00,0x00},
        {0x00,0x00,0x00,0x00},
@@ -86,25 +86,7 @@ static const UCHAR SiS300_OEMTVFlicker[8][4] =
        {0x00,0x00,0x00,0x00}
 };
 
-#if 0   /* TW: Not used */
-static const UCHAR SiS300_OEMLCDDelay1[12][4]={
-       {0x2c,0x2c,0x2c,0x2c},
-       {0x20,0x20,0x20,0x20},
-       {0x20,0x20,0x20,0x20},
-       {0x2c,0x2c,0x2c,0x2c},
-       {0x2c,0x2c,0x2c,0x2c},
-       {0x20,0x20,0x20,0x20},
-       {0x20,0x20,0x20,0x20},
-       {0x24,0x24,0x24,0x24},
-       {0x24,0x24,0x24,0x24},
-       {0x20,0x20,0x20,0x20},
-       {0x20,0x20,0x20,0x20},
-       {0x24,0x24,0x24,0x24}
-};
-#endif
-
-/* From 630/301B BIOS */
-static const UCHAR SiS300_OEMLCDDelay2[64][4] =                 /* for 301/301b/302b/301LV/302LV */
+static const unsigned char SiS300_OEMLCDDelay2[64][4] =                 /* for 301/301b/302b/301LV/302LV */
 {
        {0x20,0x20,0x20,0x20},
        {0x20,0x20,0x20,0x20},
@@ -172,8 +154,7 @@ static const UCHAR SiS300_OEMLCDDelay2[64][4] =              /* for 301/301b/302b/301LV/302
        {0x20,0x20,0x20,0x20}
 };
 
-/* From 300/301LV BIOS */
-static const UCHAR SiS300_OEMLCDDelay4[12][4] =
+static const unsigned char SiS300_OEMLCDDelay4[12][4] =
 {
        {0x2c,0x2c,0x2c,0x2c},
        {0x20,0x20,0x20,0x20},
@@ -189,8 +170,7 @@ static const UCHAR SiS300_OEMLCDDelay4[12][4] =
        {0x24,0x24,0x24,0x24}
 };
 
-/* From 300/301LV BIOS */
-static const UCHAR SiS300_OEMLCDDelay5[32][4] =
+static const unsigned char SiS300_OEMLCDDelay5[32][4] =
 {
        {0x20,0x20,0x20,0x20},
        {0x20,0x20,0x20,0x20},
@@ -226,8 +206,8 @@ static const UCHAR SiS300_OEMLCDDelay5[32][4] =
        {0x20,0x20,0x20,0x20},
 };
 
-/* Added for LVDS */
-static const UCHAR SiS300_OEMLCDDelay3[64][4] = {      /* For LVDS */
+static const unsigned char SiS300_OEMLCDDelay3[64][4] =                /* For LVDS */
+{
        {0x20,0x20,0x20,0x20},
        {0x20,0x20,0x20,0x20},
        {0x20,0x20,0x20,0x20},
@@ -294,7 +274,7 @@ static const UCHAR SiS300_OEMLCDDelay3[64][4] = {   /* For LVDS */
        {0x20,0x20,0x20,0x20}
 };
 
-static const UCHAR SiS300_Phase1[8][5][4] =
+static const unsigned char SiS300_Phase1[8][5][4] =
 {
     {
        {0x21,0xed,0x00,0x08},
@@ -354,11 +334,10 @@ static const UCHAR SiS300_Phase1[8][5][4] =
     }
 };
 
-
-static const UCHAR SiS300_Phase2[8][5][4] =
+static const unsigned char SiS300_Phase2[8][5][4] =
 {
     {
-        {0x21,0xed,0x00,0x08},
+       {0x21,0xed,0x00,0x08},
        {0x21,0xed,0x8a,0x08},
        {0x21,0xed,0x8a,0x08},
        {0x21,0xed,0x8a,0x08},
@@ -372,42 +351,42 @@ static const UCHAR SiS300_Phase2[8][5][4] =
        {0x2a,0x05,0xd3,0x00}
     },
     {
-        {0x2a,0x05,0xd3,0x00},
+       {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00}
     },
     {
-        {0x2a,0x05,0xd3,0x00},
+       {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00}
     },
     {
-        {0x21,0xed,0x00,0x08},
+       {0x21,0xed,0x00,0x08},
        {0x21,0xed,0x8a,0x08},
        {0x21,0xed,0x8a,0x08},
        {0x21,0xed,0x8a,0x08},
        {0x21,0xed,0x8a,0x08}
     },
     {
-        {0x2a,0x05,0xd3,0x00},
+       {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00}
     },
     {
-        {0x2a,0x05,0xd3,0x00},
+       {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00}
     },
     {
-        {0x2a,0x05,0xd3,0x00},
+       {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00},
@@ -415,7 +394,7 @@ static const UCHAR SiS300_Phase2[8][5][4] =
     }
 };
 
-static const UCHAR SiS300_Filter1[10][16][4] =
+static const unsigned char SiS300_Filter1[10][16][4] =
 {
     {
        {0x00,0xf4,0x10,0x38},
@@ -599,7 +578,7 @@ static const UCHAR SiS300_Filter1[10][16][4] =
     },
 };
 
-static const UCHAR SiS300_Filter2[10][9][7] =
+static const unsigned char SiS300_Filter2[10][9][7] =
 {
     {
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -714,142 +693,144 @@ static const UCHAR SiS300_Filter2[10][9][7] =
 };
 
 /* Custom data for Barco iQ Pro R300 */
-static const UCHAR barco_p1[2][9][7][3] = {
-    {
-       {  { 0x16, 0xcf, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x19, 0x00 }
-       },
-       {
-          { 0x16, 0xcf, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x1e, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x16, 0x00 }
-       },
-       {
-          { 0x16, 0xcf, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x19, 0x00 },
-          {    0,    0,    0 }
-       },
-       {
-          {    0,    0,    0 }
-       },
-       {
-          { 0x16, 0xcf, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x1e, 0x00 },
-          {    0,    0,    0 }
-       },
-       {
-          { 0x16, 0xd1, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x11, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x26, 0x00 }
-       },
-       {
-          { 0x16, 0xd1, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x30, 0x00 },
-          {    0,    0,    0 }
-       },
-       {
-          { 0x16, 0x00, 0x00 },
-          { 0x17, 0xa0, 0x00 },
-          { 0x1a, 0xa0, 0x00 },
-          { 0x1b, 0x2a, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          {    0,    0,    0 }
-       },
-       {
-          { 0x16, 0x00, 0x00 },
-          { 0x17, 0xaa, 0x00 },
-          { 0x1a, 0xa0, 0x00 },
-          { 0x1b, 0x2a, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          {    0,    0,    0 }
-       }
-    },
-    {
-       {
-          { 0x16, 0xcf, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x19, 0x00 }
-       },
-       {
-          {    0,    0,    0 }
-       },
-       {
-          { 0x16, 0xcf, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x19, 0x00 },
-       },
-       {
-          {    0,    0,    0 }
-       },
-       {
-          { 0x16, 0xcf, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe7, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x1e, 0x00 }
-       },
-       {
-          { 0x16, 0xd1, 0x00 },
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe6, 0x00 },
-          { 0x1b, 0x11, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x26, 0x00 }
-       },
-       {
-          { 0x18, 0x00, 0x00 },
-          { 0x1a, 0xe0, 0x00 },
-          { 0x1b, 0x26, 0x00 },
-          { 0x1c, 0xff, 0x00 },
-          { 0x1d, 0x1c, 0x00 },
-          { 0x1e, 0x30, 0x00 },
-          {    0,    0,    0 }
-       },
-       {
-          {    0,    0,    0 }
-       },
-       {
-          {    0,    0,    0 }
-       }
-    }
+static const unsigned char barco_p1[2][9][7][3] =
+{
+  {
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x19, 0x00 }
+     },
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x1e, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x16, 0x00 }
+     },
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x19, 0x00 },
+       {    0,    0,    0 }
+     },
+     {
+       {    0,    0,    0 }
+     },
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x1e, 0x00 },
+       {    0,    0,    0 }
+     },
+     {
+       { 0x16, 0xd1, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x11, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x26, 0x00 }
+     },
+     {
+       { 0x16, 0xd1, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x30, 0x00 },
+       {    0,    0,    0 }
+     },
+     {
+       { 0x16, 0x00, 0x00 },
+       { 0x17, 0xa0, 0x00 },
+       { 0x1a, 0xa0, 0x00 },
+       { 0x1b, 0x2a, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       {    0,    0,    0 }
+     },
+     {
+       { 0x16, 0x00, 0x00 },
+       { 0x17, 0xaa, 0x00 },
+       { 0x1a, 0xa0, 0x00 },
+       { 0x1b, 0x2a, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       {    0,    0,    0 }
+     }
+  },
+  {
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x19, 0x00 }
+     },
+     {
+       {    0,    0,    0 }
+     },
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x19, 0x00 },
+     },
+     {
+       {    0,    0,    0 }
+     },
+     {
+       { 0x16, 0xcf, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe7, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x1e, 0x00 }
+     },
+     {
+       { 0x16, 0xd1, 0x00 },
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe6, 0x00 },
+       { 0x1b, 0x11, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x26, 0x00 }
+     },
+     {
+       { 0x18, 0x00, 0x00 },
+       { 0x1a, 0xe0, 0x00 },
+       { 0x1b, 0x26, 0x00 },
+       { 0x1c, 0xff, 0x00 },
+       { 0x1d, 0x1c, 0x00 },
+       { 0x1e, 0x30, 0x00 },
+       {    0,    0,    0 }
+     },
+     {
+       {    0,    0,    0 }
+     },
+     {
+       {    0,    0,    0 }
+     }
+  }
 };
 
 
index 2b7db916b7e7e43cdb1c6e5323e42f0f7c9a2783..8fce56e4482c098253bd7fe679e1c3532f3da2dd 100644 (file)
@@ -1,9 +1,9 @@
 /* $XFree86$ */
 /* $XdotOrg$ */
 /*
- * OEM Data for 315/330 series
+ * OEM Data for 315/330/340 series
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-static const UCHAR SiS310_LCDDelayCompensation_301[] =                 /* 301 */
+static const unsigned char SiS310_LCDDelayCompensation_301[] =                 /* 301 */
 {
-                0x00,0x00,0x00,    /*   800x600 */
-                0x0b,0x0b,0x0b,    /*  1024x768 */
-                0x08,0x08,0x08,    /* 1280x1024 */
-                0x00,0x00,0x00,    /*   640x480 (unknown) */
-                0x00,0x00,0x00,    /*  1024x600 (unknown) */
-                0x00,0x00,0x00,    /*  1152x864 (unknown) */
-                0x08,0x08,0x08,    /*  1280x960 (guessed) */
-                0x00,0x00,0x00,    /*  1152x768 (unknown) */
-                0x08,0x08,0x08,    /* 1400x1050 */
-                0x08,0x08,0x08,    /*  1280x768  (guessed) */
-                0x00,0x00,0x00,    /* 1600x1200 */
-                0x00,0x00,0x00,    /*   320x480 (unknown) */
-                0x00,0x00,0x00,
-                0x00,0x00,0x00,
-                0x00,0x00,0x00
+       0x00,0x00,0x00,    /*   800x600 */
+       0x0b,0x0b,0x0b,    /*  1024x768 */
+       0x08,0x08,0x08,    /* 1280x1024 */
+       0x00,0x00,0x00,    /*   640x480 (unknown) */
+       0x00,0x00,0x00,    /*  1024x600 (unknown) */
+       0x00,0x00,0x00,    /*  1152x864 (unknown) */
+       0x08,0x08,0x08,    /*  1280x960 (guessed) */
+       0x00,0x00,0x00,    /*  1152x768 (unknown) */
+       0x08,0x08,0x08,    /* 1400x1050 */
+       0x08,0x08,0x08,    /*  1280x768  (guessed) */
+       0x00,0x00,0x00,    /* 1600x1200 */
+       0x00,0x00,0x00,    /*   320x480 (unknown) */
+       0x00,0x00,0x00,
+       0x00,0x00,0x00,
+       0x00,0x00,0x00
 };
 
 /* This is contained in 650+301B BIOSes, but it is wrong - so we don't use it */
-static const UCHAR SiS310_LCDDelayCompensation_650301LV[] =            /* 650 + 30xLV */
+static const unsigned char SiS310_LCDDelayCompensation_650301LV[] =            /* 650 + 30xLV */
 {
-                0x01,0x01,0x01,    /*   800x600 */
-                0x01,0x01,0x01,    /*  1024x768 */
-                0x01,0x01,0x01,    /* 1280x1024 */
-                 0x01,0x01,0x01,    /*   640x480 (unknown) */
-                0x01,0x01,0x01,    /*  1024x600 (unknown) */
-                0x01,0x01,0x01,    /*  1152x864 (unknown) */
-                0x01,0x01,0x01,    /*  1280x960 (guessed) */
-                0x01,0x01,0x01,    /*  1152x768 (unknown) */
-                0x01,0x01,0x01,    /* 1400x1050 */
-                0x01,0x01,0x01,    /*  1280x768  (guessed) */
-                0x01,0x01,0x01,    /* 1600x1200 */
-                0x02,0x02,0x02,
-                0x02,0x02,0x02,
-                0x02,0x02,0x02,
-                0x02,0x02,0x02
+       0x01,0x01,0x01,    /*   800x600 */
+       0x01,0x01,0x01,    /*  1024x768 */
+       0x01,0x01,0x01,    /* 1280x1024 */
+       0x01,0x01,0x01,    /*   640x480 (unknown) */
+       0x01,0x01,0x01,    /*  1024x600 (unknown) */
+       0x01,0x01,0x01,    /*  1152x864 (unknown) */
+       0x01,0x01,0x01,    /*  1280x960 (guessed) */
+       0x01,0x01,0x01,    /*  1152x768 (unknown) */
+       0x01,0x01,0x01,    /* 1400x1050 */
+       0x01,0x01,0x01,    /*  1280x768  (guessed) */
+       0x01,0x01,0x01,    /* 1600x1200 */
+       0x02,0x02,0x02,
+       0x02,0x02,0x02,
+       0x02,0x02,0x02,
+       0x02,0x02,0x02
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_651301LV[] =            /* M650/651 301LV */
+static const unsigned char SiS310_LCDDelayCompensation_651301LV[] =            /* M650/651 301LV */
 {
-                 0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
-                0x33,0x33,0x33,    /*  1024x768 */
-                0x33,0x33,0x33,    /* 1280x1024 */
-                0x33,0x33,0x33,    /*   640x480 (unknown) */
-                0x33,0x33,0x33,    /*  1024x600 (unknown) */
-                0x33,0x33,0x33,    /*  1152x864 (unknown) */
-                0x33,0x33,0x33,    /*  1280x960 (guessed) */
-                0x33,0x33,0x33,    /*  1152x768 (unknown) */
-                0x33,0x33,0x33,    /* 1400x1050 */
-                0x33,0x33,0x33,    /*  1280x768  (guessed) */
-                0x33,0x33,0x33,    /* 1600x1200 */
-                0x33,0x33,0x33,
-                0x33,0x33,0x33,
-                0x33,0x33,0x33,
-                0x33,0x33,0x33
+       0x33,0x33,0x33,    /*   800x600 (guessed) - new: PanelType, not PanelRes ! */
+       0x33,0x33,0x33,    /*  1024x768 */
+       0x33,0x33,0x33,    /* 1280x1024 */
+       0x33,0x33,0x33,    /*   640x480 (unknown) */
+       0x33,0x33,0x33,    /*  1024x600 (unknown) */
+       0x33,0x33,0x33,    /*  1152x864 (unknown) */
+       0x33,0x33,0x33,    /*  1280x960 (guessed) */
+       0x33,0x33,0x33,    /*  1152x768 (unknown) */
+       0x33,0x33,0x33,    /* 1400x1050 */
+       0x33,0x33,0x33,    /*  1280x768  (guessed) */
+       0x33,0x33,0x33,    /* 1600x1200 */
+       0x33,0x33,0x33,
+       0x33,0x33,0x33,
+       0x33,0x33,0x33,
+       0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_651302LV[] =            /* M650/651 302LV */
+static const unsigned char SiS310_LCDDelayCompensation_651302LV[] =            /* M650/651 302LV */
 {
-                 0x33,0x33,0x33,    /*   800x600 (guessed) */
-                0x33,0x33,0x33,    /*  1024x768 */
-                0x33,0x33,0x33,    /* 1280x1024 */
-                0x33,0x33,0x33,    /*   640x480 (unknown) */
-                0x33,0x33,0x33,    /*  1024x600 (unknown) */
-                0x33,0x33,0x33,    /*  1152x864 (unknown) */
-                0x33,0x33,0x33,    /*  1280x960 (guessed) */
-                0x33,0x33,0x33,    /*  1152x768 (unknown) */
-                0x33,0x33,0x33,    /* 1400x1050 */
-                0x33,0x33,0x33,    /*  1280x768  (guessed) */
-                0x33,0x33,0x33,    /* 1600x1200 */
-                0x33,0x33,0x33,
-                0x33,0x33,0x33,
-                0x33,0x33,0x33,
-                0x33,0x33,0x33
+       0x33,0x33,0x33,    /*   800x600 (guessed) */
+       0x33,0x33,0x33,    /*  1024x768 */
+       0x33,0x33,0x33,    /* 1280x1024 */
+       0x33,0x33,0x33,    /*   640x480 (unknown) */
+       0x33,0x33,0x33,    /*  1024x600 (unknown) */
+       0x33,0x33,0x33,    /*  1152x864 (unknown) */
+       0x33,0x33,0x33,    /*  1280x960 (guessed) */
+       0x33,0x33,0x33,    /*  1152x768 (unknown) */
+       0x33,0x33,0x33,    /* 1400x1050 */
+       0x33,0x33,0x33,    /*  1280x768  (guessed) */
+       0x33,0x33,0x33,    /* 1600x1200 */
+       0x33,0x33,0x33,
+       0x33,0x33,0x33,
+       0x33,0x33,0x33,
+       0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =             /* 30xB */
+static const unsigned char SiS310_LCDDelayCompensation_3xx301B[] =             /* 30xB */
 {
-                0x01,0x01,0x01,    /*   800x600 */
-                0x0C,0x0C,0x0C,    /*  1024x768 */
-                0x0C,0x0C,0x0C,    /* 1280x1024 */
-                 0x08,0x08,0x08,    /*   640x480 */
-                0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
-                0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
-                0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
-                0x02,0x02,0x02,
-                0x02,0x02,0x02,
-                0x02,0x02,0x02,
-                0x02,0x02,0x02
+       0x01,0x01,0x01,    /*   800x600 */
+       0x0C,0x0C,0x0C,    /*  1024x768 */
+       0x0C,0x0C,0x0C,    /* 1280x1024 */
+       0x08,0x08,0x08,    /*   640x480 */
+       0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+       0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+       0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+       0x02,0x02,0x02,
+       0x02,0x02,0x02,
+       0x02,0x02,0x02,
+       0x02,0x02,0x02
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] =            /* 315+30xLV */
+static const unsigned char SiS310_LCDDelayCompensation_3xx301LV[] =            /* 315+30xLV */
 {
-                0x01,0x01,0x01,    /*   800x600 */
-                0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
-                0x0C,0x0C,0x0C,    /* 1280x1024 */
-                 0x08,0x08,0x08,    /*   640x480 */
-                0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
-                0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
-                0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
-                0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
-                0x02,0x02,0x02,
-                0x02,0x02,0x02,
-                0x02,0x02,0x02,
-                0x02,0x02,0x02
+       0x01,0x01,0x01,    /*   800x600 */
+       0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+       0x0C,0x0C,0x0C,    /* 1280x1024 */
+       0x08,0x08,0x08,    /*   640x480 */
+       0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+       0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+       0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+       0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+       0x02,0x02,0x02,
+       0x02,0x02,0x02,
+       0x02,0x02,0x02,
+       0x02,0x02,0x02
 };
 
-static const UCHAR SiS310_TVDelayCompensation_301[] =          /* 301 */
+static const unsigned char SiS310_TVDelayCompensation_301[] =          /* 301 */
 {
-                0x02,0x02,    /* NTSC Enhanced, Standard */
-                 0x02,0x02,    /* PAL */
-                0x08,0x0b     /* HiVision */
+       0x02,0x02,    /* NTSC Enhanced, Standard */
+       0x02,0x02,    /* PAL */
+       0x08,0x0b     /* HiVision */
 };
 
-static const UCHAR SiS310_TVDelayCompensation_301B[] =         /* 30xB, 30xLV */
+static const unsigned char SiS310_TVDelayCompensation_301B[] =         /* 30xB, 30xLV */
 {
-                0x03,0x03,
-                0x03,0x03,
-                0x03,0x03
+       0x03,0x03,
+       0x03,0x03,
+       0x03,0x03
 };
 
-static const UCHAR SiS310_TVDelayCompensation_740301B[] =      /* 740 + 30xB (30xLV?) */
+static const unsigned char SiS310_TVDelayCompensation_740301B[] =      /* 740 + 30xB (30xLV?) */
 {
-                0x05,0x05,
-                0x05,0x05,
-                0x05,0x05
+       0x05,0x05,
+       0x05,0x05,
+       0x05,0x05
 };
 
-static const UCHAR SiS310_TVDelayCompensation_651301LV[] =     /* M650, 651, 301LV */
+static const unsigned char SiS310_TVDelayCompensation_651301LV[] =     /* M650, 651, 301LV */
 {
-                0x33,0x33,
-                0x33,0x33,
-                0x33,0x33
+       0x33,0x33,
+       0x33,0x33,
+       0x33,0x33
 };
 
-static const UCHAR SiS310_TVDelayCompensation_651302LV[] =     /* M650, 651, 302LV */
+static const unsigned char SiS310_TVDelayCompensation_651302LV[] =     /* M650, 651, 302LV */
 {
-                0x33,0x33,
-                0x33,0x33,
-                0x33,0x33
+       0x33,0x33,
+       0x33,0x33,
+       0x33,0x33
 };
 
-static const UCHAR SiS_TVDelay661_301[] =                      /* 661, 301 */
+static const unsigned char SiS_TVDelay661_301[] =                      /* 661, 301 */
 {
-                0x44,0x44,
-                0x44,0x44,
-                0x00,0x00,
-                0x44,0x44,
-                0x44,0x44,
-                0x44,0x44
+       0x44,0x44,
+       0x44,0x44,
+       0x00,0x00,
+       0x44,0x44,
+       0x44,0x44,
+       0x44,0x44
 };
 
-static const UCHAR SiS_TVDelay661_301B[] =                     /* 661, 301B et al */
+static const unsigned char SiS_TVDelay661_301B[] =                     /* 661, 301B et al */
 {
-                0x44,0x44,
-                0x44,0x44,
-                0x00,0x00,
-                0x44,0x44,
-                0x44,0x44,
-                0x44,0x44
+       0x44,0x44,
+       0x44,0x44,
+       0x00,0x00,
+       0x44,0x44,
+       0x44,0x44,
+       0x44,0x44
 };
 
-static const UCHAR SiS310_TVDelayCompensation_LVDS[] =         /* LVDS */
+static const unsigned char SiS310_TVDelayCompensation_LVDS[] =         /* LVDS */
 {
-                0x0a,0x0a,
-                0x0a,0x0a,
-                0x0a,0x0a
+       0x0a,0x0a,
+       0x0a,0x0a,
+       0x0a,0x0a
 };
 
-static const UCHAR SiS310_TVAntiFlick1[6][2] =
+static const unsigned char SiS310_TVAntiFlick1[6][2] =
 {
-            {0x4,0x0},
-           {0x4,0x8},
-           {0x0,0x0},
-           {0x0,0x0},
-           {0x0,0x0},
-           {0x0,0x0}
+       {0x4,0x0},
+       {0x4,0x8},
+       {0x0,0x0},
+       {0x0,0x0},
+       {0x0,0x0},
+       {0x0,0x0}
 };
 
-static const UCHAR SiS310_TVEdge1[6][2] =
+static const unsigned char SiS310_TVEdge1[6][2] =
 {
-            {0x0,0x4},
-           {0x0,0x4},
-           {0x0,0x0},
-           {0x0,0x0},
-           {0x0,0x0},
-           {0x0,0x0}
+       {0x0,0x4},
+       {0x0,0x4},
+       {0x0,0x0},
+       {0x0,0x0},
+       {0x0,0x0},
+       {0x0,0x0}
 };
 
-static const UCHAR SiS310_TVYFilter1[5][8][4] =
+static const unsigned char SiS310_TVYFilter1[5][8][4] =
 {
- {
  {
        {0x00,0xf4,0x10,0x38},  /* NTSC */
        {0x00,0xf4,0x10,0x38},
        {0xeb,0x04,0x25,0x18},
@@ -258,8 +258,8 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
        {0xeb,0x04,0x25,0x18},
        {0xee,0x0c,0x22,0x08},
        {0xeb,0x15,0x25,0xf6}
- },
- {
  },
  {
        {0x00,0xf4,0x10,0x38},  /* PAL */
        {0x00,0xf4,0x10,0x38},
        {0xf1,0xf7,0x1f,0x32},
@@ -268,8 +268,8 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
        {0xf1,0xf7,0x1f,0x32},
        {0xf3,0x00,0x1d,0x20},
        {0xfc,0xfb,0x14,0x2a}
- },
- {
  },
  {
        {0x00,0x00,0x00,0x00},  /* HiVision */
        {0x00,0xf4,0x10,0x38},
        {0x00,0xf4,0x10,0x38},
@@ -278,9 +278,9 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
        {0x00,0xf4,0x10,0x38},
        {0xeb,0x04,0x25,0x18},
        {0xee,0x0c,0x22,0x08}
- },
- {
-       {0x00,0xf4,0x10,0x38},  /* PAL-M */
  },
  {
+       {0x00,0xf4,0x10,0x38},  /* PAL-M */
        {0x00,0xf4,0x10,0x38},
        {0xeb,0x04,0x10,0x18},
        {0xf7,0x06,0x19,0x14},
@@ -288,9 +288,9 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
        {0xeb,0x04,0x25,0x18},
        {0xeb,0x04,0x25,0x18},
        {0xeb,0x15,0x25,0xf6}
- },
- {
-       {0x00,0xf4,0x10,0x38},  /* PAL-N */
  },
  {
+       {0x00,0xf4,0x10,0x38},  /* PAL-N */
        {0x00,0xf4,0x10,0x38},
        {0xeb,0x04,0x10,0x18},
        {0xf7,0x06,0x19,0x14},
@@ -298,12 +298,12 @@ static const UCHAR SiS310_TVYFilter1[5][8][4] =
        {0xeb,0x04,0x25,0x18},
        {0xeb,0x04,0x25,0x18},
        {0xeb,0x15,0x25,0xf6}
- }
  }
 };
 
-static const UCHAR SiS310_TVYFilter2[5][9][7] =
+static const unsigned char SiS310_TVYFilter2[5][9][7] =
 {
- {
  {
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* NTSC */
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -313,8 +313,8 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
        {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
  },
  {
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL */
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
@@ -324,8 +324,8 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
        {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
  },
  {
        {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},   /* HiVision */
        {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
        {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
@@ -335,9 +335,9 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
        {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
        {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22},
        {0x00,0x00,0x00,0xF4,0xFF,0x1C,0x22}
- },
- {
-       {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL-M */
  },
  {
+       {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL-M */
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
@@ -346,9 +346,9 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
        {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- },
- {
-       {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL-N */
  },
  {
+       {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},   /* PAL-N */
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0xFF,0x03,0x02,0xF6,0xFC,0x27,0x46},
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
@@ -357,58 +357,39 @@ static const UCHAR SiS310_TVYFilter2[5][9][7] =
        {0x01,0x02,0xFE,0xF7,0x03,0x27,0x3C},
        {0x01,0x01,0xFC,0xF8,0x08,0x26,0x38},
        {0xFF,0xFF,0xFC,0x00,0x0F,0x22,0x28}
- }
  }
 };
 
-static const UCHAR SiS310_TVPhaseIncr1[3][2][4] =
+static const unsigned char SiS310_TVPhaseIncr1[3][2][4] =
 {
- {
  {
        {0x21,0xed,0xba,0x08},
        {0x21,0xed,0xba,0x08}
- },
- {
  },
  {
        {0x2a,0x05,0xe3,0x00},
        {0x2a,0x05,0xe3,0x00}
- },
- {
  },
  {
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00}
- }
  }
 };
 
-static const UCHAR SiS310_TVPhaseIncr2[3][2][4] =
+static const unsigned char SiS310_TVPhaseIncr2[3][2][4] =
 {
- {
  {
        {0x21,0xf0,0x7b,0xd6},
        {0x21,0xf0,0x7b,0xd6}
- },
- {
  },
  {
        {0x2a,0x0a,0x41,0xe9},
        {0x2a,0x0a,0x41,0xe9}
- },
- {
  },
  {
        {0x2a,0x05,0xd3,0x00},
        {0x2a,0x05,0xd3,0x00}
- }
-};
-
-static const UCHAR SiS661_TVPhase[] = {
-    0x21,0xED,0xBA,0x08,
-    0x2A,0x05,0xE3,0x00,
-    0x21,0xE4,0x2E,0x9B,
-    0x21,0xF4,0x3E,0xBA,
-    0x1E,0x8B,0xA2,0xA7,
-    0x1E,0x83,0x0A,0xE0,
-    0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,
-    0x21,0xF0,0x7B,0xD6,
-    0x2A,0x09,0x86,0xE9,
-    0x21,0xE6,0xEF,0xA4,
-    0x21,0xF6,0x94,0x46,
-    0x1E,0x8B,0xA2,0xA7,
-    0x1E,0x83,0x0A,0xE0,
-    0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00
+   }
 };
 
 /**************************************************************/
@@ -417,7 +398,7 @@ static const UCHAR SiS661_TVPhase[] = {
 
 /* Inventec / Compaq Presario 3045US, 3017 */
 
-static const SiS_LCDDataStruct  SiS310_ExtCompaq1280x1024Data[] =
+static const struct SiS_LCDData SiS310_ExtCompaq1280x1024Data[] =
 {
        {  211,  60,1024, 501,1688,1066},
        {  211,  60,1024, 508,1688,1066},
@@ -431,17 +412,17 @@ static const SiS_LCDDataStruct  SiS310_ExtCompaq1280x1024Data[] =
 
 /* Asus A2xxxH _2 */
 
-static const SiS_Part2PortTblStruct SiS310_CRT2Part2_Asus1024x768_3[] =
+static const struct SiS_Part2PortTbl SiS310_CRT2Part2_Asus1024x768_3[] =
 {
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
- {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
- {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
      {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x2c,0x13,0x9a,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
      {{0x38,0x13,0x13,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}},
      {{0x38,0x13,0x16,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
      {{0x36,0x13,0x13,0x25,0xff,0x5a,0x45,0x0a,0x07,0xfa,0x0a,0x24}},
      {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
      {{0x25,0x13,0xc9,0x25,0xff,0x59,0x45,0x09,0x07,0xf9,0x09,0x24}}
 };
 
 
index 15939b0577131b80b3fb0de73d522ebcae9f02d1..841ca3190cd4d15fbe329763016a0e5639698bc9 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * OS depending defines
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
 #define _SIS_OSDEF_H_
 
 /* The choices are: */
-#define LINUX_KERNEL      /* Linux kernel framebuffer */
-/* #define LINUX_XF86 */   /* XFree86/X.org */
+#define SIS_LINUX_KERNEL               /* Linux kernel framebuffer */
+#undef  SIS_XORG_XF86                  /* XFree86/X.org */
+
+#undef SIS_LINUX_KERNEL_24
+#undef SIS_LINUX_KERNEL_26
 
 #ifdef OutPortByte
 #undef OutPortByte
@@ -86,8 +89,9 @@
 /*  LINUX KERNEL                                                      */
 /**********************************************************************/
 
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
 #include <linux/config.h>
+#include <linux/version.h>
 
 #ifdef CONFIG_FB_SIS_300
 #define SIS300
 #define SIS315H
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define SIS_LINUX_KERNEL_26
+#else
+#define SIS_LINUX_KERNEL_24
+#endif
+
 #if !defined(SIS300) && !defined(SIS315H)
 #warning Neither CONFIG_FB_SIS_300 nor CONFIG_FB_SIS_315 is set
 #warning sisfb will not work!
 #define InPortWord(p)    inw((SISIOADDRESS)(p))
 #define InPortLong(p)    inl((SISIOADDRESS)(p))
 #define SiS_SetMemory(MemoryAddress,MemorySize,value) memset_io(MemoryAddress, value, MemorySize)
-#endif
+
+#endif /* LINUX_KERNEL */
 
 /**********************************************************************/
 /*  XFree86/X.org                                                    */
 /**********************************************************************/
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
+
 #define SIS300
 #define SIS315H
 
 #define InPortWord(p)    inSISREGW((IOADDRESS)(p))
 #define InPortLong(p)    inSISREGL((IOADDRESS)(p))
 #define SiS_SetMemory(MemoryAddress,MemorySize,value) memset(MemoryAddress, value, MemorySize)
-#endif
+
+#endif /* XF86 */
 
 #endif  /* _OSDEF_H_ */
index d0103c162e43bf525c0a3d9caee25111983c4634..0b6e625d7331672d5ff8e6ab04d42a02adb2cf74 100644 (file)
@@ -1,8 +1,10 @@
 /*
- * SiS 300/630/730/540/315/550/[M]650/651/[M]661[FM]X/740/[M]741[GX]/330/[M]760[GX]
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]661[F|M]X/740/[M]741[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
  * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
  *
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
  *
  * 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
@@ -19,8 +21,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  */
 
-#ifndef _SIS_H
-#define _SIS_H
+#ifndef _SIS_H_
+#define _SIS_H_
 
 #include <linux/config.h>
 #include <linux/version.h>
 #include "vgatypes.h"
 #include "vstruct.h"
 
-#define VER_MAJOR                 1
-#define VER_MINOR                 7
-#define VER_LEVEL                 17
-
-#undef SIS_CONFIG_COMPAT
+#define VER_MAJOR              1
+#define VER_MINOR              8
+#define VER_LEVEL              9
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #include <linux/spinlock.h>
+#define SIS_PCI_GET_CLASS(a, b) pci_get_class(a, b)
+#define SIS_PCI_GET_DEVICE(a,b,c) pci_get_device(a,b,c)
+#define SIS_PCI_GET_SLOT(a,b) pci_get_slot(a,b)
+#define SIS_PCI_PUT_DEVICE(a) pci_dev_put(a)
 #ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
 #include <linux/ioctl32.h>
-#define SIS_CONFIG_COMPAT
-#endif
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
-#ifdef __x86_64__
-/* Shouldn't we check for CONFIG_IA32_EMULATION here? */
+#define SIS_OLD_CONFIG_COMPAT
+#else
+#include <linux/smp_lock.h>
+#define SIS_NEW_CONFIG_COMPAT
+#endif
+#endif /* CONFIG_COMPAT */
+#else  /* 2.4 */
+#define SIS_PCI_GET_CLASS(a, b) pci_find_class(a, b)
+#define SIS_PCI_GET_DEVICE(a,b,c) pci_find_device(a,b,c)
+#define SIS_PCI_GET_SLOT(a,b) pci_find_slot(a,b)
+#define SIS_PCI_PUT_DEVICE(a)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
+#ifdef __x86_64__      /* Shouldn't we check for CONFIG_IA32_EMULATION here? */
 #include <asm/ioctl32.h>
-#define SIS_CONFIG_COMPAT
+#define SIS_OLD_CONFIG_COMPAT
 #endif
 #endif
-
+#endif /* 2.4 */
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
 #define SIS_IOTYPE1 void __iomem
 #define SIS_IOTYPE2 __iomem
 
 /* To be included in pci_ids.h */
 #ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA  0x6325
+#define PCI_DEVICE_ID_SI_650_VGA       0x6325
 #endif
 #ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650      0x0650
+#define PCI_DEVICE_ID_SI_650           0x0650
 #endif
 #ifndef PCI_DEVICE_ID_SI_651
-#define PCI_DEVICE_ID_SI_651      0x0651
+#define PCI_DEVICE_ID_SI_651           0x0651
 #endif
 #ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740      0x0740
+#define PCI_DEVICE_ID_SI_740           0x0740
 #endif
 #ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330      0x0330
+#define PCI_DEVICE_ID_SI_330           0x0330
 #endif
 #ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA  0x6330
+#define PCI_DEVICE_ID_SI_660_VGA       0x6330
 #endif
 #ifndef PCI_DEVICE_ID_SI_661
-#define PCI_DEVICE_ID_SI_661      0x0661
+#define PCI_DEVICE_ID_SI_661           0x0661
 #endif
 #ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741      0x0741
+#define PCI_DEVICE_ID_SI_741           0x0741
 #endif
 #ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0660
+#define PCI_DEVICE_ID_SI_660           0x0660
 #endif
 #ifndef PCI_DEVICE_ID_SI_760
-#define PCI_DEVICE_ID_SI_760      0x0760
+#define PCI_DEVICE_ID_SI_760           0x0760
+#endif
+#ifndef PCI_DEVICE_ID_SI_761
+#define PCI_DEVICE_ID_SI_761           0x0761
+#endif
+
+#ifndef PCI_VENDOR_ID_XGI
+#define PCI_VENDOR_ID_XGI              0x18ca
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_20
+#define PCI_DEVICE_ID_XGI_20           0x0020
+#endif
+
+#ifndef PCI_DEVICE_ID_XGI_40
+#define PCI_DEVICE_ID_XGI_40           0x0040
 #endif
 
 /* To be included in fb.h */
 #ifndef FB_ACCEL_SIS_GLAMOUR_2
-#define FB_ACCEL_SIS_GLAMOUR_2   40    /* SiS 315, 65x, 740, 661, 741  */
+#define FB_ACCEL_SIS_GLAMOUR_2 40      /* SiS 315, 65x, 740, 661, 741  */
 #endif
 #ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE        41   /* SiS 330 ("Xabre"), 760       */
+#define FB_ACCEL_SIS_XABRE     41      /* SiS 330 ("Xabre"), 76x       */
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_V
+#define FB_ACCEL_XGI_VOLARI_V  47      /* XGI Volari Vx (V3XT, V5, V8) */
+#endif
+#ifndef FB_ACCEL_XGI_VOLARI_Z
+#define FB_ACCEL_XGI_VOLARI_Z  48      /* XGI Volari Z7                */
 #endif
-
-#define MAX_ROM_SCAN              0x10000
 
 /* ivideo->caps */
-#define HW_CURSOR_CAP             0x80
-#define TURBO_QUEUE_CAP           0x40
-#define AGP_CMD_QUEUE_CAP         0x20
-#define VM_CMD_QUEUE_CAP          0x10
-#define MMIO_CMD_QUEUE_CAP        0x08
+#define HW_CURSOR_CAP          0x80
+#define TURBO_QUEUE_CAP                0x40
+#define AGP_CMD_QUEUE_CAP      0x20
+#define VM_CMD_QUEUE_CAP       0x10
+#define MMIO_CMD_QUEUE_CAP     0x08
 
 /* For 300 series */
-#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
-#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
+#define TURBO_QUEUE_AREA_SIZE  (512 * 1024)    /* 512K */
+#define HW_CURSOR_AREA_SIZE_300        4096            /* 4K */
 
 /* For 315/Xabre series */
-#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD   0x1F
-#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
-
-#define SIS_OH_ALLOC_SIZE         4000
-#define SENTINEL                  0x7fffffff
-
-#define SEQ_ADR                   0x14
-#define SEQ_DATA                  0x15
-#define DAC_ADR                   0x18
-#define DAC_DATA                  0x19
-#define CRTC_ADR                  0x24
-#define CRTC_DATA                 0x25
-#define DAC2_ADR                  (0x16-0x30)
-#define DAC2_DATA                 (0x17-0x30)
-#define VB_PART1_ADR              (0x04-0x30)
-#define VB_PART1_DATA             (0x05-0x30)
-#define VB_PART2_ADR              (0x10-0x30)
-#define VB_PART2_DATA             (0x11-0x30)
-#define VB_PART3_ADR              (0x12-0x30)
-#define VB_PART3_DATA             (0x13-0x30)
-#define VB_PART4_ADR              (0x14-0x30)
-#define VB_PART4_DATA             (0x15-0x30)
-
-#define SISSR                    ivideo->SiS_Pr.SiS_P3c4
-#define SISCR                     ivideo->SiS_Pr.SiS_P3d4
-#define SISDACA                   ivideo->SiS_Pr.SiS_P3c8
-#define SISDACD                   ivideo->SiS_Pr.SiS_P3c9
-#define SISPART1                  ivideo->SiS_Pr.SiS_Part1Port
-#define SISPART2                  ivideo->SiS_Pr.SiS_Part2Port
-#define SISPART3                  ivideo->SiS_Pr.SiS_Part3Port
-#define SISPART4                  ivideo->SiS_Pr.SiS_Part4Port
-#define SISPART5                  ivideo->SiS_Pr.SiS_Part5Port
-#define SISDAC2A                  SISPART5
-#define SISDAC2D                  (SISPART5 + 1)
-#define SISMISCR                  (ivideo->SiS_Pr.RelIO + 0x1c)
-#define SISMISCW                  ivideo->SiS_Pr.SiS_P3c2
-#define SISINPSTAT               (ivideo->SiS_Pr.RelIO + 0x2a)
-#define SISPEL                   ivideo->SiS_Pr.SiS_P3c6
-
-#define IND_SIS_PASSWORD          0x05  /* SRs */
-#define IND_SIS_COLOR_MODE        0x06
-#define IND_SIS_RAMDAC_CONTROL    0x07
-#define IND_SIS_DRAM_SIZE         0x14
-#define IND_SIS_MODULE_ENABLE     0x1E
-#define IND_SIS_PCI_ADDRESS_SET   0x20
-#define IND_SIS_TURBOQUEUE_ADR    0x26
-#define IND_SIS_TURBOQUEUE_SET    0x27
-#define IND_SIS_POWER_ON_TRAP     0x38
-#define IND_SIS_POWER_ON_TRAP2    0x39
-#define IND_SIS_CMDQUEUE_SET      0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
-
-#define IND_SIS_AGP_IO_PAD        0x48
-
-#define SIS_CRT2_WENABLE_300     0x24  /* Part1 */
-#define SIS_CRT2_WENABLE_315     0x2F
-
-#define SIS_PASSWORD              0x86  /* SR05 */
-
-#define SIS_INTERLACED_MODE       0x20  /* SR06 */
-#define SIS_8BPP_COLOR_MODE       0x0
-#define SIS_15BPP_COLOR_MODE      0x1
-#define SIS_16BPP_COLOR_MODE      0x2
-#define SIS_32BPP_COLOR_MODE      0x4
-
-#define SIS_ENABLE_2D             0x40  /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
-#define SIS_PCI_ADDR_ENABLE       0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/330 series SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
-#define SIS_MMIO_CMD_ENABLE       0x20
-#define SIS_CMD_QUEUE_SIZE_512k   0x00
-#define SIS_CMD_QUEUE_SIZE_1M     0x04
-#define SIS_CMD_QUEUE_SIZE_2M     0x08
-#define SIS_CMD_QUEUE_SIZE_4M     0x0C
-#define SIS_CMD_QUEUE_RESET       0x01
-#define SIS_CMD_AUTO_CORR        0x02
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
-#define SIS_MODE_SELECT_CRT2      0x02
-#define SIS_VB_OUTPUT_COMPOSITE   0x04
-#define SIS_VB_OUTPUT_SVIDEO      0x08
-#define SIS_VB_OUTPUT_SCART       0x10
-#define SIS_VB_OUTPUT_LCD         0x20
-#define SIS_VB_OUTPUT_CRT2        0x40
-#define SIS_VB_OUTPUT_HIVISION    0x80
-
-#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
-#define SIS_DRIVER_MODE           0x40
-
-#define SIS_VB_COMPOSITE          0x01  /* CR32 */
-#define SIS_VB_SVIDEO             0x02
-#define SIS_VB_SCART              0x04
-#define SIS_VB_LCD                0x08
-#define SIS_VB_CRT2               0x10
-#define SIS_CRT1                  0x20
-#define SIS_VB_HIVISION           0x40
-#define SIS_VB_YPBPR              0x80
-#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
-                                   SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
-
-#define SIS_EXTERNAL_CHIP_MASK            0x0E  /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS             0x02
-#define SIS_EXTERNAL_CHIP_TRUMPION         0x03
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04
-#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05
-#define SIS310_EXTERNAL_CHIP_LVDS          0x02
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03
-
-#define SIS_AGP_2X                0x20  /* CR48 */
-
-#define HW_DEVICE_EXTENSION      SIS_HW_INFO
-#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
+#define COMMAND_QUEUE_AREA_SIZE        (512 * 1024)    /* 512K */
+#define COMMAND_QUEUE_AREA_SIZE_Z7 (128 * 1024)        /* 128k for XGI Z7 */
+#define HW_CURSOR_AREA_SIZE_315        16384           /* 16K */
+#define COMMAND_QUEUE_THRESHOLD        0x1F
+
+#define SIS_OH_ALLOC_SIZE      4000
+#define SENTINEL               0x7fffffff
+
+#define SEQ_ADR                        0x14
+#define SEQ_DATA               0x15
+#define DAC_ADR                        0x18
+#define DAC_DATA               0x19
+#define CRTC_ADR               0x24
+#define CRTC_DATA              0x25
+#define DAC2_ADR               (0x16-0x30)
+#define DAC2_DATA              (0x17-0x30)
+#define VB_PART1_ADR           (0x04-0x30)
+#define VB_PART1_DATA          (0x05-0x30)
+#define VB_PART2_ADR           (0x10-0x30)
+#define VB_PART2_DATA          (0x11-0x30)
+#define VB_PART3_ADR           (0x12-0x30)
+#define VB_PART3_DATA          (0x13-0x30)
+#define VB_PART4_ADR           (0x14-0x30)
+#define VB_PART4_DATA          (0x15-0x30)
+
+#define SISSR                  ivideo->SiS_Pr.SiS_P3c4
+#define SISCR                  ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA                        ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD                        ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1               ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2               ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3               ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4               ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5               ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A               SISPART5
+#define SISDAC2D               (SISPART5 + 1)
+#define SISMISCR               (ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW               ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT             (ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL                 ivideo->SiS_Pr.SiS_P3c6
+#define SISVGAENABLE           (ivideo->SiS_Pr.RelIO + 0x13)
+#define SISVID                 (ivideo->SiS_Pr.RelIO + 0x02 - 0x30)
+#define SISCAP                 (ivideo->SiS_Pr.RelIO + 0x00 - 0x30)
+
+#define IND_SIS_PASSWORD               0x05  /* SRs */
+#define IND_SIS_COLOR_MODE             0x06
+#define IND_SIS_RAMDAC_CONTROL         0x07
+#define IND_SIS_DRAM_SIZE              0x14
+#define IND_SIS_MODULE_ENABLE          0x1E
+#define IND_SIS_PCI_ADDRESS_SET                0x20
+#define IND_SIS_TURBOQUEUE_ADR         0x26
+#define IND_SIS_TURBOQUEUE_SET         0x27
+#define IND_SIS_POWER_ON_TRAP          0x38
+#define IND_SIS_POWER_ON_TRAP2         0x39
+#define IND_SIS_CMDQUEUE_SET           0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD     0x27
+
+#define IND_SIS_AGP_IO_PAD     0x48
+
+#define SIS_CRT2_WENABLE_300   0x24  /* Part1 */
+#define SIS_CRT2_WENABLE_315   0x2F
+
+#define SIS_PASSWORD           0x86  /* SR05 */
+
+#define SIS_INTERLACED_MODE    0x20  /* SR06 */
+#define SIS_8BPP_COLOR_MODE    0x0
+#define SIS_15BPP_COLOR_MODE   0x1
+#define SIS_16BPP_COLOR_MODE   0x2
+#define SIS_32BPP_COLOR_MODE   0x4
+
+#define SIS_ENABLE_2D          0x40  /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE  0x01  /* SR20 */
+#define SIS_PCI_ADDR_ENABLE    0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE                0x80  /* 315/330/340 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE       0x40
+#define SIS_MMIO_CMD_ENABLE            0x20
+#define SIS_CMD_QUEUE_SIZE_512k                0x00
+#define SIS_CMD_QUEUE_SIZE_1M          0x04
+#define SIS_CMD_QUEUE_SIZE_2M          0x08
+#define SIS_CMD_QUEUE_SIZE_4M          0x0C
+#define SIS_CMD_QUEUE_RESET            0x01
+#define SIS_CMD_AUTO_CORR              0x02
+
+#define SIS_CMD_QUEUE_SIZE_Z7_64k      0x00 /* XGI Z7 */
+#define SIS_CMD_QUEUE_SIZE_Z7_128k     0x04
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE   0x01  /* CR30 */
+#define SIS_MODE_SELECT_CRT2           0x02
+#define SIS_VB_OUTPUT_COMPOSITE                0x04
+#define SIS_VB_OUTPUT_SVIDEO           0x08
+#define SIS_VB_OUTPUT_SCART            0x10
+#define SIS_VB_OUTPUT_LCD              0x20
+#define SIS_VB_OUTPUT_CRT2             0x40
+#define SIS_VB_OUTPUT_HIVISION         0x80
+
+#define SIS_VB_OUTPUT_DISABLE  0x20  /* CR31 */
+#define SIS_DRIVER_MODE                0x40
+
+#define SIS_VB_COMPOSITE       0x01  /* CR32 */
+#define SIS_VB_SVIDEO          0x02
+#define SIS_VB_SCART           0x04
+#define SIS_VB_LCD             0x08
+#define SIS_VB_CRT2            0x10
+#define SIS_CRT1               0x20
+#define SIS_VB_HIVISION                0x40
+#define SIS_VB_YPBPR           0x80
+#define SIS_VB_TV              (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+                               SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK                 0x0E  /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301               0x01  /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS                 0x02
+#define SIS_EXTERNAL_CHIP_TRUMPION             0x03
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL                0x04
+#define SIS_EXTERNAL_CHIP_CHRONTEL             0x05
+#define SIS310_EXTERNAL_CHIP_LVDS              0x02
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL     0x03
+
+#define SIS_AGP_2X             0x20  /* CR48 */
+
+/* vbflags, private entries (others in sisfb.h) */
+#define VB_CONEXANT            0x00000800      /* 661 series only */
+#define VB_TRUMPION            VB_CONEXANT     /* 300 series only */
+#define VB_302ELV              0x00004000
+#define VB_301                 0x00100000      /* Video bridge type */
+#define VB_301B                        0x00200000
+#define VB_302B                        0x00400000
+#define VB_30xBDH              0x00800000      /* 30xB DH version (w/o LCD support) */
+#define VB_LVDS                        0x01000000
+#define VB_CHRONTEL            0x02000000
+#define VB_301LV               0x04000000
+#define VB_302LV               0x08000000
+#define VB_301C                        0x10000000
+
+#define VB_SISBRIDGE           (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
+#define VB_VIDEOBRIDGE         (VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
+
+/* vbflags2 (static stuff only!) */
+#define VB2_SISUMC             0x00000001
+#define VB2_301                        0x00000002      /* Video bridge type */
+#define VB2_301B               0x00000004
+#define VB2_301C               0x00000008
+#define VB2_307T               0x00000010
+#define VB2_302B               0x00000800
+#define VB2_301LV              0x00001000
+#define VB2_302LV              0x00002000
+#define VB2_302ELV             0x00004000
+#define VB2_307LV              0x00008000
+#define VB2_30xBDH             0x08000000      /* 30xB DH version (w/o LCD support) */
+#define VB2_CONEXANT           0x10000000
+#define VB2_TRUMPION           0x20000000
+#define VB2_LVDS               0x40000000
+#define VB2_CHRONTEL           0x80000000
+
+#define VB2_SISLVDSBRIDGE      (VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_SISTMDSBRIDGE      (VB2_301   | VB2_301B  | VB2_301C   | VB2_302B | VB2_307T)
+#define VB2_SISBRIDGE          (VB2_SISLVDSBRIDGE | VB2_SISTMDSBRIDGE)
+
+#define VB2_SISTMDSLCDABRIDGE  (VB2_301C | VB2_307T)
+#define VB2_SISLCDABRIDGE      (VB2_SISTMDSLCDABRIDGE | VB2_301LV | VB2_302LV | VB2_302ELV | VB2_307LV)
+
+#define VB2_SISHIVISIONBRIDGE  (VB2_301  | VB2_301B | VB2_302B)
+#define VB2_SISYPBPRBRIDGE     (VB2_301C | VB2_307T | VB2_SISLVDSBRIDGE)
+#define VB2_SISYPBPRARBRIDGE   (VB2_301C | VB2_307T | VB2_307LV)
+#define VB2_SISTAP4SCALER      (VB2_301C | VB2_307T | VB2_302ELV | VB2_307LV)
+#define VB2_SISTVBRIDGE                (VB2_SISHIVISIONBRIDGE | VB2_SISYPBPRBRIDGE)
+
+#define VB2_SISVGA2BRIDGE      (VB2_301 | VB2_301B | VB2_301C | VB2_302B | VB2_307T)
+
+#define VB2_VIDEOBRIDGE                (VB2_SISBRIDGE | VB2_LVDS | VB2_CHRONTEL | VB2_CONEXANT)
+
+#define VB2_30xB               (VB2_301B  | VB2_301C   | VB2_302B  | VB2_307T)
+#define VB2_30xBLV             (VB2_30xB  | VB2_SISLVDSBRIDGE)
+#define VB2_30xC               (VB2_301C  | VB2_307T)
+#define VB2_30xCLV             (VB2_301C  | VB2_307T   | VB2_302ELV| VB2_307LV)
+#define VB2_SISEMIBRIDGE       (VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCD162MHZBRIDGE    (VB2_301C  | VB2_307T)
+#define VB2_LCDOVER1280BRIDGE  (VB2_301C  | VB2_307T   | VB2_302LV | VB2_302ELV | VB2_307LV)
+#define VB2_LCDOVER1600BRIDGE  (VB2_307T  | VB2_307LV)
+#define VB2_RAMDAC202MHZBRIDGE (VB2_301C  | VB2_307T)
 
 /* I/O port access macros */
-#define inSISREG(base)          inb(base)
+#define inSISREG(base)         inb(base)
 
-#define outSISREG(base,val)     outb(val,base)
+#define outSISREG(base,val)    outb(val,base)
 
 #define orSISREG(base,val)                             \
-                   do {                                \
-                      u8 __Temp = inSISREG(base);      \
-                      outSISREG(base, __Temp | (val));         \
-                    } while (0)
+               do {                                    \
+                       u8 __Temp = inSISREG(base);     \
+                       outSISREG(base, __Temp | (val));\
+               } while (0)
 
 #define andSISREG(base,val)                            \
-                   do {                                \
-                      u8 __Temp = inSISREG(base);      \
-                      outSISREG(base, __Temp & (val));         \
-                    } while (0)
-
-#define inSISIDXREG(base,idx,var)              \
-                   do {                        \
-                      outSISREG(base, idx);    \
-                     var = inSISREG((base)+1); \
-                    } while (0)
-
-#define outSISIDXREG(base,idx,val)             \
-                   do {                        \
-                      outSISREG(base, idx);    \
-                     outSISREG((base)+1, val); \
-                    } while (0)
-
-#define orSISIDXREG(base,idx,val)                              \
-                   do {                                        \
-                      u8 __Temp;                               \
-                      outSISREG(base, idx);                    \
-                      __Temp = inSISREG((base)+1) | (val);     \
-                     outSISREG((base)+1, __Temp);              \
-                    } while (0)
-
-#define andSISIDXREG(base,idx,and)                             \
-                   do {                                        \
-                      u8 __Temp;                               \
-                      outSISREG(base, idx);                    \
-                      __Temp = inSISREG((base)+1) & (and);     \
-                     outSISREG((base)+1, __Temp);              \
-                    } while (0)
-
-#define setSISIDXREG(base,idx,and,or)                                  \
-                   do {                                                \
-                      u8 __Temp;                                       \
-                      outSISREG(base, idx);                            \
-                      __Temp = (inSISREG((base)+1) & (and)) | (or);    \
-                     outSISREG((base)+1, __Temp);                      \
-                    } while (0)
+               do {                                    \
+                       u8 __Temp = inSISREG(base);     \
+                       outSISREG(base, __Temp & (val));\
+               } while (0)
+
+#define inSISIDXREG(base,idx,var)                      \
+               do {                                    \
+                       outSISREG(base, idx);           \
+                       var = inSISREG((base)+1);       \
+               } while (0)
+
+#define outSISIDXREG(base,idx,val)                     \
+               do {                                    \
+                       outSISREG(base, idx);           \
+                       outSISREG((base)+1, val);       \
+               } while (0)
+
+#define orSISIDXREG(base,idx,val)                              \
+               do {                                            \
+                       u8 __Temp;                              \
+                       outSISREG(base, idx);                   \
+                       __Temp = inSISREG((base)+1) | (val);    \
+                       outSISREG((base)+1, __Temp);            \
+               } while (0)
+
+#define andSISIDXREG(base,idx,and)                             \
+               do {                                            \
+                       u8 __Temp;                              \
+                       outSISREG(base, idx);                   \
+                       __Temp = inSISREG((base)+1) & (and);    \
+                       outSISREG((base)+1, __Temp);            \
+               } while (0)
+
+#define setSISIDXREG(base,idx,and,or)                                  \
+               do {                                                    \
+                       u8 __Temp;                                      \
+                       outSISREG(base, idx);                           \
+                       __Temp = (inSISREG((base)+1) & (and)) | (or);   \
+                       outSISREG((base)+1, __Temp);                    \
+               } while (0)
 
 /* MMIO access macros */
 #define MMIO_IN8(base, offset)  readb((base+offset))
 #define MMIO_QUEUE_READPORT     Q_READ_PTR
 
 #ifndef FB_BLANK_UNBLANK
-#define FB_BLANK_UNBLANK       0
+#define FB_BLANK_UNBLANK       0
 #endif
 #ifndef FB_BLANK_NORMAL
-#define FB_BLANK_NORMAL        1
+#define FB_BLANK_NORMAL                1
 #endif
 #ifndef FB_BLANK_VSYNC_SUSPEND
-#define FB_BLANK_VSYNC_SUSPEND         2
+#define FB_BLANK_VSYNC_SUSPEND 2
 #endif
 #ifndef FB_BLANK_HSYNC_SUSPEND
-#define FB_BLANK_HSYNC_SUSPEND         3
+#define FB_BLANK_HSYNC_SUSPEND 3
 #endif
 #ifndef FB_BLANK_POWERDOWN
-#define FB_BLANK_POWERDOWN     4
+#define FB_BLANK_POWERDOWN     4
 #endif
 
 enum _SIS_LCD_TYPE {
@@ -347,18 +444,19 @@ enum _SIS_LCD_TYPE {
     LCD_1600x1200,
     LCD_1920x1440,
     LCD_2048x1536,
-    LCD_320x480,       /* FSTN */
+    LCD_320x240,       /* FSTN */
     LCD_1400x1050,
     LCD_1152x864,
     LCD_1152x768,
     LCD_1280x768,
     LCD_1024x600,
-    LCD_640x480_2,     /* DSTN */
-    LCD_640x480_3,     /* DSTN */
+    LCD_320x240_2,     /* DSTN */
+    LCD_320x240_3,     /* DSTN */
     LCD_848x480,
     LCD_1280x800,
     LCD_1680x1050,
     LCD_1280x720,
+    LCD_1280x854,
     LCD_CUSTOM,
     LCD_UNKNOWN
 };
@@ -368,31 +466,50 @@ enum _SIS_CMDTYPE {
     AGP_CMD_QUEUE,
     VM_CMD_QUEUE,
 };
-typedef unsigned int SIS_CMDTYPE;
+
+struct SIS_OH {
+       struct SIS_OH *poh_next;
+       struct SIS_OH *poh_prev;
+       u32            offset;
+       u32            size;
+};
+
+struct SIS_OHALLOC {
+       struct SIS_OHALLOC *poha_next;
+       struct SIS_OH aoh[1];
+};
+
+struct SIS_HEAP {
+       struct SIS_OH   oh_free;
+       struct SIS_OH   oh_used;
+       struct SIS_OH   *poh_freelist;
+       struct SIS_OHALLOC *poha_chain;
+       u32             max_freesize;
+       struct sis_video_info *vinfo;
+};
 
 /* Our "par" */
 struct sis_video_info {
        int             cardnumber;
        struct fb_info  *memyselfandi;
 
-       SIS_HW_INFO     sishw_ext;
-       SiS_Private     SiS_Pr;
+       struct SiS_Private SiS_Pr;
 
-       sisfb_info      sisfbinfo;      /* For ioctl SISFB_GET_INFO */
+       struct sisfb_info sisfbinfo;    /* For ioctl SISFB_GET_INFO */
 
        struct fb_var_screeninfo default_var;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
        struct fb_fix_screeninfo sisfb_fix;
-       u32             pseudo_palette[17];
+       u32             pseudo_palette[17];
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       struct display           sis_disp;
+       struct display           sis_disp;
        struct display_switch    sisfb_sw;
        struct {
                u16 red, green, blue, pad;
-       }               sis_palette[256];
+       }               sis_palette[256];
        union {
 #ifdef FBCON_HAS_CFB16
                u16 cfb16[16];
@@ -400,10 +517,10 @@ struct sis_video_info {
 #ifdef FBCON_HAS_CFB32
                u32 cfb32[16];
 #endif
-       }               sis_fbcon_cmap;
+       }               sis_fbcon_cmap;
 #endif
 
-        struct sisfb_monitor {
+       struct sisfb_monitor {
                u16 hmin;
                u16 hmax;
                u16 vmin;
@@ -411,163 +528,166 @@ struct sis_video_info {
                u32 dclockmax;
                u8  feature;
                BOOLEAN datavalid;
-       }               sisfb_thismonitor;
+       }               sisfb_thismonitor;
 
-       int             chip_id;
+       unsigned short  chip_id;        /* PCI ID of chip */
+       unsigned short  chip_vendor;    /* PCI ID of vendor */
        char            myid[40];
 
        struct pci_dev  *nbridge;
+       struct pci_dev  *lpcdev;
 
        int             mni;    /* Mode number index */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       int             currcon;
+       int             currcon;
 #endif
 
        unsigned long   video_size;
-       unsigned long   video_base;
+       unsigned long   video_base;
        unsigned long   mmio_size;
-       unsigned long   mmio_base;
-       unsigned long   vga_base;
+       unsigned long   mmio_base;
+       unsigned long   vga_base;
+
+       unsigned long   video_offset;
 
-       SIS_IOTYPE1     *video_vbase;
-       SIS_IOTYPE1     *mmio_vbase;
+       unsigned long   UMAsize, LFBsize;
 
-       unsigned char   *bios_abase;
+       SIS_IOTYPE1     *video_vbase;
+       SIS_IOTYPE1     *mmio_vbase;
 
-       int             mtrr;
+       unsigned char   *bios_abase;
+
+       int             mtrr;
 
        u32             sisfb_mem;
 
-       u32             sisfb_parm_mem;
-       int             sisfb_accel;
-       int             sisfb_ypan;
-       int             sisfb_max;
-       int             sisfb_userom;
-       int             sisfb_useoem;
+       u32             sisfb_parm_mem;
+       int             sisfb_accel;
+       int             sisfb_ypan;
+       int             sisfb_max;
+       int             sisfb_userom;
+       int             sisfb_useoem;
        int             sisfb_mode_idx;
        int             sisfb_parm_rate;
        int             sisfb_crt1off;
        int             sisfb_forcecrt1;
        int             sisfb_crt2type;
        int             sisfb_crt2flags;
-       int             sisfb_dstn;
-       int             sisfb_fstn;
+       int             sisfb_dstn;
+       int             sisfb_fstn;
        int             sisfb_tvplug;
        int             sisfb_tvstd;
-       int             sisfb_filter;
        int             sisfb_nocrt2rate;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        int             sisfb_inverse;
 #endif
 
-       u32             heapstart;              /* offset  */
-       SIS_IOTYPE1     *sisfb_heap_start;      /* address */
-       SIS_IOTYPE1     *sisfb_heap_end;        /* address */
-       u32             sisfb_heap_size;
+       u32             heapstart;              /* offset  */
+       SIS_IOTYPE1     *sisfb_heap_start;      /* address */
+       SIS_IOTYPE1     *sisfb_heap_end;        /* address */
+       u32             sisfb_heap_size;
        int             havenoheap;
-#if 0
-       SIS_HEAP        sisfb_heap;
-#endif
 
+       struct SIS_HEAP sisfb_heap;             /* This card's vram heap */
 
-       int             video_bpp;
-       int             video_cmap_len;
-       int             video_width;
-       int             video_height;
-       unsigned int    refresh_rate;
+       int             video_bpp;
+       int             video_cmap_len;
+       int             video_width;
+       int             video_height;
+       unsigned int    refresh_rate;
 
-       unsigned int    chip;
-       u8              revision_id;
+       unsigned int    chip;
+       u8              revision_id;
+       int             sisvga_enabled;         /* PCI device was enabled */
 
-       int             video_linelength;       /* real pitch */
+       int             video_linelength;       /* real pitch */
        int             scrnpitchCRT1;          /* pitch regarding interlace */
 
-        u16            DstColor;               /* For 2d acceleration */
-       u32             SiS310_AccelDepth;
-       u32             CommandReg;
-       int             cmdqueuelength;
+       u16             DstColor;               /* For 2d acceleration */
+       u32             SiS310_AccelDepth;
+       u32             CommandReg;
+       int             cmdqueuelength;         /* Current (for accel) */
+       u32             cmdQueueSize;           /* Total size in KB */
 
-       spinlock_t      lockaccel;              /* Do not use outside of kernel! */
+       spinlock_t      lockaccel;              /* Do not use outside of kernel! */
 
-        unsigned int           pcibus;
-       unsigned int    pcislot;
-       unsigned int    pcifunc;
+       unsigned int    pcibus;
+       unsigned int    pcislot;
+       unsigned int    pcifunc;
 
-       int             accel;
+       int             accel;
+       int             engineok;
 
-       u16             subsysvendor;
-       u16             subsysdevice;
+       u16             subsysvendor;
+       u16             subsysdevice;
 
-       u32             vbflags;                /* Replacing deprecated stuff from above */
-       u32             currentvbflags;
+       u32             vbflags;                /* Replacing deprecated stuff from above */
+       u32             currentvbflags;
+       u32             vbflags2;
 
        int             lcdxres, lcdyres;
        int             lcddefmodeidx, tvdefmodeidx, defmodeidx;
-       u32             CRT2LCDType;            /* defined in "SIS_LCD_TYPE" */
-
-       int             current_bpp;
-       int             current_width;
-       int             current_height;
-       int             current_htotal;
-       int             current_vtotal;
+       u32             CRT2LCDType;            /* defined in "SIS_LCD_TYPE" */
+       u32             curFSTN, curDSTN;
+
+       int             current_bpp;
+       int             current_width;
+       int             current_height;
+       int             current_htotal;
+       int             current_vtotal;
        int             current_linelength;
-       __u32           current_pixclock;
-       int             current_refresh_rate;
+       __u32           current_pixclock;
+       int             current_refresh_rate;
+
+       unsigned int    current_base;
 
-       u8              mode_no;
-       u8              rate_idx;
-       int             modechanged;
-       unsigned char   modeprechange;
+       u8              mode_no;
+       u8              rate_idx;
+       int             modechanged;
+       unsigned char   modeprechange;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-       u8              sisfb_lastrates[128];
+       u8              sisfb_lastrates[128];
 #endif
 
-       int             newrom;
-       int             registered;
+       int             newrom;
+       int             haveXGIROM;
+       int             registered;
        int             warncount;
+#ifdef SIS_OLD_CONFIG_COMPAT
+       int             ioctl32registered;
+#endif
 
-       int             sisvga_engine;
-       int             hwcursor_size;
-       int             CRT2_write_enable;
-       u8              caps;
+       int             sisvga_engine;
+       int             hwcursor_size;
+       int             CRT2_write_enable;
+       u8              caps;
 
-       u8              detectedpdc;
-       u8              detectedpdca;
-       u8              detectedlcda;
+       u8              detectedpdc;
+       u8              detectedpdca;
+       u8              detectedlcda;
 
-       SIS_IOTYPE1     *hwcursor_vbase;
+       SIS_IOTYPE1     *hwcursor_vbase;
 
-       int             chronteltype;
-       int             tvxpos, tvypos;
-       u8              p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+       int             chronteltype;
+       int             tvxpos, tvypos;
+       u8              p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
        int             tvx, tvy;
 
-       u8              sisfblocked;
+       u8              sisfblocked;
+
+       struct sisfb_info sisfb_infoblock;
+
+       struct sisfb_cmd sisfb_command;
+
+       u32             sisfb_id;
+
+       u8              sisfb_can_post;
+       u8              sisfb_card_posted;
+       u8              sisfb_was_boot_device;
 
        struct sis_video_info *next;
 };
 
-typedef struct _SIS_OH {
-       struct _SIS_OH *poh_next;
-       struct _SIS_OH *poh_prev;
-       u32            offset;
-       u32            size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
-       struct _SIS_OHALLOC *poha_next;
-       SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
-       SIS_OH      oh_free;
-       SIS_OH      oh_used;
-       SIS_OH      *poh_freelist;
-       SIS_OHALLOC *poha_chain;
-       u32         max_freesize;
-       struct sis_video_info *vinfo;
-} SIS_HEAP;
-
 #endif
index 30e90a553e8090500a660c9b624fa22bab8ef629..bab933e6c6a697ffe8dcd804517b69c8363506b8 100644 (file)
@@ -1,6 +1,8 @@
 /*
- * SiS 300/630/730/540/315/550/65x/74x/330/760 frame buffer driver
- * for Linux kernels 2.4.x and 2.6.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
  * 2D acceleration part
  *
@@ -19,7 +21,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  *
  * Based on the XFree86/X.org driver which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ *     Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * Author: Thomas Winischhofer <thomas@winischhofer.net>
  *                     (see http://www.winischhofer.net/
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/fb.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <linux/console.h>
-#include <linux/selection.h>
+#endif
 #include <linux/ioport.h>
-#include <linux/capability.h>
-#include <linux/fs.h>
 #include <linux/types.h>
 
 #include <asm/io.h>
@@ -188,7 +188,7 @@ SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
 }
 #endif
 
-/* 315/330 series ------------------------------------------------- */
+/* 315/330/340 series ---------------------------------------------- */
 
 #ifdef CONFIG_FB_SIS_315
 static void
@@ -202,7 +202,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
 {
        SiS310SetupDSTColorDepth(ivideo->DstColor);
        SiS310SetupSRCPitch(ivideo->video_linelength)
-       SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+       SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
        if(trans_color != -1) {
                SiS310SetupROP(0x0A)
                SiS310SetupSRCTrans(trans_color)
@@ -213,7 +213,7 @@ SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int tra
                /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
        }
        SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
-       /* The 315 series is smart enough to know the direction */
+       /* The chip is smart enough to know the direction */
 }
 
 static void
@@ -223,35 +223,38 @@ SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int
        u32 srcbase = 0, dstbase = 0;
        int mymin = min(src_y, dst_y);
        int mymax = max(src_y, dst_y);
-       
+
        /* Although the chip knows the direction to use
-        * if the source and destination areas overlap, 
+        * if the source and destination areas overlap,
         * that logic fails if we fiddle with the bitmap
         * addresses. Therefore, we check if the source
-        * and destination blitting areas overlap and 
-        * adapt the bitmap addresses synchronously 
+        * and destination blitting areas overlap and
+        * adapt the bitmap addresses synchronously
         * if the coordinates exceed the valid range.
-        * The the areas do not overlap, we do our 
+        * The the areas do not overlap, we do our
         * normal check.
         */
-       if((mymax - mymin) < height) { 
-          if((src_y >= 2048) || (dst_y >= 2048)) {           
-             srcbase = ivideo->video_linelength * mymin;
-             dstbase = ivideo->video_linelength * mymin;
-             src_y -= mymin;
-             dst_y -= mymin;
-          }
+       if((mymax - mymin) < height) {
+               if((src_y >= 2048) || (dst_y >= 2048)) {
+                       srcbase = ivideo->video_linelength * mymin;
+                       dstbase = ivideo->video_linelength * mymin;
+                       src_y -= mymin;
+                       dst_y -= mymin;
+               }
        } else {
-          if(src_y >= 2048) {
-             srcbase = ivideo->video_linelength * src_y;
-             src_y = 0;
-          }
-          if(dst_y >= 2048) {
-             dstbase = ivideo->video_linelength * dst_y;
-             dst_y = 0;
-          }
+               if(src_y >= 2048) {
+                       srcbase = ivideo->video_linelength * src_y;
+                       src_y = 0;
+               }
+               if(dst_y >= 2048) {
+                       dstbase = ivideo->video_linelength * dst_y;
+                       dst_y = 0;
+               }
        }
 
+       srcbase += ivideo->video_offset;
+       dstbase += ivideo->video_offset;
+
        SiS310SetupSRCBase(srcbase);
        SiS310SetupDSTBase(dstbase);
        SiS310SetupRect(width, height)
@@ -264,7 +267,7 @@ static void
 SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
        SiS310SetupPATFG(color)
-       SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+       SiS310SetupDSTRect(ivideo->video_linelength, 0x0fff)
        SiS310SetupDSTColorDepth(ivideo->DstColor);
        SiS310SetupROP(sisPatALUConv[rop])
        SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
@@ -279,6 +282,7 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
                dstbase = ivideo->video_linelength * y;
                y = 0;
        }
+       dstbase += ivideo->video_offset;
        SiS310SetupDSTBase(dstbase)
        SiS310SetupDSTXY(x,y)
        SiS310SetupRect(w,h)
@@ -294,384 +298,153 @@ SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w
 int sisfb_initaccel(struct sis_video_info *ivideo)
 {
 #ifdef SISFB_USE_SPINLOCKS
-    spin_lock_init(&ivideo->lockaccel);
+       spin_lock_init(&ivideo->lockaccel);
 #endif
-    return(0);
+       return 0;
 }
 
 void sisfb_syncaccel(struct sis_video_info *ivideo)
 {
-    if(ivideo->sisvga_engine == SIS_300_VGA) {
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-       SiS300Sync(ivideo);
+               SiS300Sync(ivideo);
 #endif
-    } else {
+       } else {
 #ifdef CONFIG_FB_SIS_315
-       SiS310Sync(ivideo);
+               SiS310Sync(ivideo);
 #endif
-    }
+       }
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)  /* --------------- 2.5 --------------- */
 
 int fbcon_sis_sync(struct fb_info *info)
 {
-   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-   CRITFLAGS
+       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+       CRITFLAGS
 
-   if(!ivideo->accel)
-       return 0;
+       if((!ivideo->accel) || (!ivideo->engineok))
+               return 0;
 
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-      SiS300Sync(ivideo);
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      SiS310Sync(ivideo);
-#endif
-   }
-   CRITEND
-   return 0;
+       CRITBEGIN
+       sisfb_syncaccel(ivideo);
+       CRITEND
+
+       return 0;
 }
 
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-   u32 col = 0;
-   u32 vxres = info->var.xres_virtual;
-   u32 vyres = info->var.yres_virtual;
-   int width, height;
-   CRITFLAGS
-
-   if(info->state != FBINFO_STATE_RUNNING) {
-       return;
-   }
-
-   if(!ivideo->accel) {
-       cfb_fillrect(info, rect);
-       return;
-   }
-   
-   if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
-       return;
-   }
-
-   /* Clipping */
-   width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
-   height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
-
-   switch(info->var.bits_per_pixel) {
+       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+       u32 col = 0;
+       u32 vxres = info->var.xres_virtual;
+       u32 vyres = info->var.yres_virtual;
+       int width, height;
+       CRITFLAGS
+
+       if(info->state != FBINFO_STATE_RUNNING)
+               return;
+
+       if((!ivideo->accel) || (!ivideo->engineok)) {
+               cfb_fillrect(info, rect);
+               return;
+       }
+
+       if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres)
+               return;
+
+       /* Clipping */
+       width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+       height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+
+       switch(info->var.bits_per_pixel) {
        case 8:  col = rect->color;
                 break;
        case 16:
        case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
                 break;
-   }
+       }
 
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-      CRITBEGIN
-      SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
-      SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
-      CRITEND
-      SiS300Sync(ivideo);
+               CRITBEGIN
+               SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+               SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+               CRITEND
 #endif
-   } else {
+       } else {
 #ifdef CONFIG_FB_SIS_315
-      CRITBEGIN
-      SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
-      SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
-      CRITEND
-      SiS310Sync(ivideo);
+               CRITBEGIN
+               SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+               SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
+               CRITEND
 #endif
-   }
+       }
 
+       sisfb_syncaccel(ivideo);
 }
 
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-   u32 vxres = info->var.xres_virtual;
-   u32 vyres = info->var.yres_virtual;
-   int width = area->width;
-   int height = area->height;
-   CRITFLAGS
-
-   if(info->state != FBINFO_STATE_RUNNING) {
-       return;
-   }
-
-   if(!ivideo->accel) {
-       cfb_copyarea(info, area);
-       return;
-   }
-
-   if(!width || !height ||
-      area->sx >= vxres || area->sy >= vyres ||
-      area->dx >= vxres || area->dy >= vyres) {
-       return;
-   }
-
-   /* Clipping */
-   if((area->sx + width) > vxres) width = vxres - area->sx;
-   if((area->dx + width) > vxres) width = vxres - area->dx;
-   if((area->sy + height) > vyres) height = vyres - area->sy;
-   if((area->dy + height) > vyres) height = vyres - area->dy;
-
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-      int xdir, ydir;
-
-      if(area->sx < area->dx) xdir = 0;
-      else                    xdir = 1;
-      if(area->sy < area->dy) ydir = 0;
-      else                    ydir = 1;
-
-      CRITBEGIN
-      SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
-      SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
-                                        width, height);
-      CRITEND
-      SiS300Sync(ivideo);
-#endif
-   } else {
-#ifdef CONFIG_FB_SIS_315
-      CRITBEGIN
-      SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
-      SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy,
-                                        width, height);
-      CRITEND
-      SiS310Sync(ivideo);
-#endif
-   }
-}
-
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)  /* -------------- 2.4 --------------- */
-
-void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
-                           int dsty, int dstx, int height, int width)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-
+       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+       u32 vxres = info->var.xres_virtual;
+       u32 vyres = info->var.yres_virtual;
+       int width = area->width;
+       int height = area->height;
        CRITFLAGS
 
-       if(!ivideo->accel) {
-           switch(ivideo->video_bpp) {
-           case 8:
-#ifdef FBCON_HAS_CFB8
-              fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
-              break;
-           case 16:
-#ifdef FBCON_HAS_CFB16
-              fbcon_cfb16_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
-              break;
-           case 32:
-#ifdef FBCON_HAS_CFB32
-              fbcon_cfb32_bmove(p, srcy, srcx, dsty, dstx, height, width);
-#endif
-              break;
-            }
-           return;
-       }
-
-       srcx *= fontwidth(p);
-       srcy *= fontheight(p);
-       dstx *= fontwidth(p);
-       dsty *= fontheight(p);
-       width *= fontwidth(p);
-       height *= fontheight(p);
+       if(info->state != FBINFO_STATE_RUNNING)
+               return;
 
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-          int xdir, ydir;
-
-          if(srcx < dstx) xdir = 0;
-          else            xdir = 1;
-          if(srcy < dsty) ydir = 0;
-          else            ydir = 1;
-
-          CRITBEGIN
-          SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
-          SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
-          CRITEND
-          SiS300Sync(ivideo);
-#endif
-       } else {
-#ifdef CONFIG_FB_SIS_315
-          CRITBEGIN
-          SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
-          SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
-          CRITEND
-          SiS310Sync(ivideo);
-#endif
+       if((!ivideo->accel) || (!ivideo->engineok)) {
+               cfb_copyarea(info, area);
+               return;
        }
-}
 
-static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width, int color)
-{
-        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       CRITFLAGS
+       if(!width || !height ||
+          area->sx >= vxres || area->sy >= vyres ||
+          area->dx >= vxres || area->dy >= vyres)
+               return;
 
-       srcx *= fontwidth(p);
-       srcy *= fontheight(p);
-       width *= fontwidth(p);
-       height *= fontheight(p);
+       /* Clipping */
+       if((area->sx + width) > vxres) width = vxres - area->sx;
+       if((area->dx + width) > vxres) width = vxres - area->dx;
+       if((area->sy + height) > vyres) height = vyres - area->sy;
+       if((area->dy + height) > vyres) height = vyres - area->dy;
 
        if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-          CRITBEGIN
-          SiS300SetupForSolidFill(ivideo, color, 3);
-          SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
-          CRITEND
-          SiS300Sync(ivideo);
+               int xdir, ydir;
+
+               if(area->sx < area->dx) xdir = 0;
+               else                    xdir = 1;
+               if(area->sy < area->dy) ydir = 0;
+               else                    ydir = 1;
+
+               CRITBEGIN
+               SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+               SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+                                       area->dx, area->dy, width, height);
+               CRITEND
 #endif
        } else {
 #ifdef CONFIG_FB_SIS_315
-          CRITBEGIN
-          SiS310SetupForSolidFill(ivideo, color, 3);
-          SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
-          CRITEND
-          SiS310Sync(ivideo);
-#endif
-       }
-}
-
-void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       u32 bgx;
-
-       if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB8
-           fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
+               CRITBEGIN
+               SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+               SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy,
+                                       area->dx, area->dy, width, height);
+               CRITEND
 #endif
-           return;
        }
 
-       bgx = attr_bgcol_ec(p, conp);
-       fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
+       sisfb_syncaccel(ivideo);
 }
 
-void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width)
-{
-        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       u32 bgx;
-
-       if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB16
-           fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
 #endif
-           return;
-       }
-
-       bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
 
-void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
-                       int srcy, int srcx, int height, int width)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       u32 bgx;
-
-       if(!ivideo->accel) {
-#ifdef FBCON_HAS_CFB32
-           fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
-#endif
-           return;
-       }
-
-       bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
-       fbcon_sis_clear(conp, p, srcy, srcx, height, width, bgx);
-}
-
-void fbcon_sis_revc(struct display *p, int srcx, int srcy)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
-       CRITFLAGS
-
-       if(!ivideo->accel) {
-           switch(ivideo->video_bpp) {
-           case 16:
-#ifdef FBCON_HAS_CFB16
-              fbcon_cfb16_revc(p, srcx, srcy);
-#endif
-              break;
-           case 32:
-#ifdef FBCON_HAS_CFB32
-              fbcon_cfb32_revc(p, srcx, srcy);
-#endif
-              break;
-            }
-           return;
-       }
-
-       srcx *= fontwidth(p);
-       srcy *= fontheight(p);
-
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-          CRITBEGIN
-          SiS300SetupForSolidFill(ivideo, 0, 0x0a);
-          SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
-          CRITEND
-          SiS300Sync(ivideo);
-#endif
-       } else {
-#ifdef CONFIG_FB_SIS_315
-          CRITBEGIN
-          SiS310SetupForSolidFill(ivideo, 0, 0x0a);
-          SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
-          CRITEND
-          SiS310Sync(ivideo);
-#endif
-       }
-}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)  /* -------------- 2.4 --------------- */
 
-#ifdef FBCON_HAS_CFB8
-struct display_switch fbcon_sis8 = {
-       .setup          = fbcon_cfb8_setup,
-       .bmove          = fbcon_sis_bmove,
-       .clear          = fbcon_sis_clear8,
-       .putc           = fbcon_cfb8_putc,
-       .putcs          = fbcon_cfb8_putcs,
-       .revc           = fbcon_cfb8_revc,
-       .clear_margins  = fbcon_cfb8_clear_margins,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB16
-struct display_switch fbcon_sis16 = {
-       .setup          = fbcon_cfb16_setup,
-       .bmove          = fbcon_sis_bmove,
-       .clear          = fbcon_sis_clear16,
-       .putc           = fbcon_cfb16_putc,
-       .putcs          = fbcon_cfb16_putcs,
-       .revc           = fbcon_sis_revc,
-       .clear_margins  = fbcon_cfb16_clear_margins,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
-#ifdef FBCON_HAS_CFB32
-struct display_switch fbcon_sis32 = {
-       .setup          = fbcon_cfb32_setup,
-       .bmove          = fbcon_sis_bmove,
-       .clear          = fbcon_sis_clear32,
-       .putc           = fbcon_cfb32_putc,
-       .putcs          = fbcon_cfb32_putcs,
-       .revc           = fbcon_sis_revc,
-       .clear_margins  = fbcon_cfb32_clear_margins,
-       .fontwidthmask  = FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
-};
-#endif
+#include "sisfb_accel_2_4.h"
 
 #endif /* KERNEL VERSION */
 
index bb28f331d60d315354145faf27f8fa328332eee0..046e2c4a8e09cac082a317bf548826fe85b70b3e 100644 (file)
@@ -1,6 +1,8 @@
 /*
- * SiS 300/630/730/540/315/550/650/740 frame buffer driver
- * for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]650/651/[M]661[F|M]X/740/[M]741[GX]/330/[M]760[GX],
+ * XGI V3XT/V5/V8, Z7
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
  * 2D acceleration part
  *
   { \
        while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
        while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+       while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+       while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
        CmdQueLen = 0; \
   }
 
@@ -402,6 +406,7 @@ void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy,
                        int srcx, int height, int width);
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+int  fbcon_sis_sync(struct fb_info *info);
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
 #endif
index 6982660368193735cc2034c9f68dee1627b028b5..42c54b69726e8b769ada57f5c90ac7eedd5bf093 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * SiS 300/540/630[S]/730[S],
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
  * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
  *
  * 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  *
- * Author:     Thomas Winischhofer <thomas@winischhofer.net>
+ * Author:     Thomas Winischhofer <thomas@winischhofer.net>
  *
  * Author of (practically wiped) code base:
  *             SiS (www.sis.com)
- *             Copyright (C) 1999 Silicon Integrated Systems, Inc.
+ *             Copyright (C) 1999 Silicon Integrated Systems, Inc.
  *
  * See http://www.winischhofer.net/ for more information and updates
  *
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/slab.h>
-#include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/console.h>
 #include <linux/selection.h>
-#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <linux/vt_kern.h>
+#endif
 #include <linux/capability.h>
 #include <linux/fs.h>
 #include <linux/types.h>
@@ -94,71 +94,75 @@ extern struct display_switch fbcon_sis32;
 #endif
 #endif
 
+static void sisfb_handle_command(struct sis_video_info *ivideo,
+                                struct sisfb_cmd *sisfb_command);
+
 /* ------------------ Internal helper routines ----------------- */
 
 static void __init
 sisfb_setdefaultparms(void)
 {
-       sisfb_off               = 0;
-       sisfb_parm_mem          = 0;
-       sisfb_accel             = -1;
-       sisfb_ypan              = -1;
-       sisfb_max               = -1;
-       sisfb_userom            = -1;
-        sisfb_useoem           = -1;
+       sisfb_off               = 0;
+       sisfb_parm_mem          = 0;
+       sisfb_accel             = -1;
+       sisfb_ypan              = -1;
+       sisfb_max               = -1;
+       sisfb_userom            = -1;
+       sisfb_useoem            = -1;
 #ifdef MODULE
        /* Module: "None" for 2.4, default mode for 2.5+ */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-       sisfb_mode_idx          = -1;
+       sisfb_mode_idx          = -1;
 #else
-       sisfb_mode_idx          = MODE_INDEX_NONE;
+       sisfb_mode_idx          = MODE_INDEX_NONE;
 #endif
 #else
        /* Static: Default mode */
-       sisfb_mode_idx          = -1;
-#endif
-       sisfb_parm_rate         = -1;
-       sisfb_crt1off           = 0;
-       sisfb_forcecrt1         = -1;
-       sisfb_crt2type          = -1;
-       sisfb_crt2flags         = 0;
-       sisfb_pdc               = 0xff;
-       sisfb_pdca              = 0xff;
-       sisfb_scalelcd          = -1;
+       sisfb_mode_idx          = -1;
+#endif
+       sisfb_parm_rate         = -1;
+       sisfb_crt1off           = 0;
+       sisfb_forcecrt1         = -1;
+       sisfb_crt2type          = -1;
+       sisfb_crt2flags         = 0;
+       sisfb_pdc               = 0xff;
+       sisfb_pdca              = 0xff;
+       sisfb_scalelcd          = -1;
        sisfb_specialtiming     = CUT_NONE;
-       sisfb_lvdshl            = -1;
-       sisfb_dstn              = 0;
-       sisfb_fstn              = 0;
-       sisfb_tvplug            = -1;
-       sisfb_tvstd             = -1;
-       sisfb_tvxposoffset      = 0;
-       sisfb_tvyposoffset      = 0;
-       sisfb_filter            = -1;
-       sisfb_nocrt2rate        = 0;
+       sisfb_lvdshl            = -1;
+       sisfb_dstn              = 0;
+       sisfb_fstn              = 0;
+       sisfb_tvplug            = -1;
+       sisfb_tvstd             = -1;
+       sisfb_tvxposoffset      = 0;
+       sisfb_tvyposoffset      = 0;
+       sisfb_nocrt2rate        = 0;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       sisfb_inverse           = 0;
-       sisfb_fontname[0]       = 0;
+       sisfb_inverse           = 0;
+       sisfb_fontname[0]       = 0;
 #endif
 #if !defined(__i386__) && !defined(__x86_64__)
-       sisfb_resetcard         = 0;
-       sisfb_videoram          = 0;
+       sisfb_resetcard         = 0;
+       sisfb_videoram          = 0;
 #endif
 }
 
+/* ------------- Parameter parsing -------------- */
+
 static void __devinit
 sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
 {
        int i = 0, j = 0;
 
-       /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+       /* We don't know the hardware specs yet and there is no ivideo */
 
        if(vesamode == 0) {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
                sisfb_mode_idx = MODE_INDEX_NONE;
 #else
-               if(!quiet) {
-                  printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
-               }
+               if(!quiet)
+                       printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+
                sisfb_mode_idx = DEFAULT_MODE;
 #endif
                return;
@@ -169,95 +173,102 @@ sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
        while(sisbios_mode[i++].mode_no[0] != 0) {
                if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
                    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
-                   if(sisfb_fstn) {
-                      if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
-                         sisbios_mode[i-1].mode_no[1] == 0x56 ||
-                         sisbios_mode[i-1].mode_no[1] == 0x53) continue;
-                   } else {
-                      if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
-                         sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
-                   }
-                   sisfb_mode_idx = i - 1;
-                   j = 1;
-                   break;
+                       if(sisfb_fstn) {
+                               if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+                                  sisbios_mode[i-1].mode_no[1] == 0x56 ||
+                                  sisbios_mode[i-1].mode_no[1] == 0x53)
+                                       continue;
+                       } else {
+                               if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+                                  sisbios_mode[i-1].mode_no[1] == 0x5b)
+                                       continue;
+                       }
+                       sisfb_mode_idx = i - 1;
+                       j = 1;
+                       break;
                }
        }
-       if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
+       if((!j) && !quiet)
+               printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
 }
 
-static void
+static void __devinit
 sisfb_search_mode(char *name, BOOLEAN quiet)
 {
-       int i = 0;
        unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
+       int i = 0;
        char strbuf[16], strbuf1[20];
        char *nameptr = name;
 
-       /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+       /* We don't know the hardware specs yet and there is no ivideo */
 
        if(name == NULL) {
-          if(!quiet) {
-             printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
-          }
-          sisfb_mode_idx = DEFAULT_MODE;
-          return;
+               if(!quiet)
+                       printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+
+               sisfb_mode_idx = DEFAULT_MODE;
+               return;
        }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-        if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
-          if(!quiet) {
-             printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-          }
-          sisfb_mode_idx = DEFAULT_MODE;
-          return;
+       if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+               if(!quiet)
+                       printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+
+               sisfb_mode_idx = DEFAULT_MODE;
+               return;
        }
 #endif
        if(strlen(name) <= 19) {
-          strcpy(strbuf1, name);
-          for(i=0; i<strlen(strbuf1); i++) {
-             if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
-          }
+               strcpy(strbuf1, name);
+               for(i = 0; i < strlen(strbuf1); i++) {
+                       if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
+               }
 
-          /* This does some fuzzy mode naming detection */
-          if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
-             if((rate <= 32) || (depth > 32)) {
-                j = rate; rate = depth; depth = j;
-             }
-             sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-             nameptr = strbuf;
-             sisfb_parm_rate = rate;
-          } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
-             sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-             nameptr = strbuf;
-          } else {
-             xres = 0;
-             if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
-                sprintf(strbuf, "%ux%ux8", xres, yres);
-                nameptr = strbuf;
-             } else {
-                sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
-                return;
-             }
-          }
+               /* This does some fuzzy mode naming detection */
+               if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
+                       if((rate <= 32) || (depth > 32)) {
+                               j = rate; rate = depth; depth = j;
+                       }
+                       sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+                       nameptr = strbuf;
+                       sisfb_parm_rate = rate;
+               } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
+                       sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+                       nameptr = strbuf;
+               } else {
+                       xres = 0;
+                       if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
+                               sprintf(strbuf, "%ux%ux8", xres, yres);
+                               nameptr = strbuf;
+                       } else {
+                               sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
+                               return;
+                       }
+               }
        }
 
        i = 0; j = 0;
        while(sisbios_mode[i].mode_no[0] != 0) {
                if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
-                       if(sisfb_fstn) {
-                               if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
-                                  sisbios_mode[i-1].mode_no[1] == 0x56 ||
-                                  sisbios_mode[i-1].mode_no[1] == 0x53) continue;
-                       } else {
-                               if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
-                                  sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
-                       }
-                       sisfb_mode_idx = i - 1;
-                       j = 1;
-                       break;
-               }
-       }
-       if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
+                       if(sisfb_fstn) {
+                               if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+                                  sisbios_mode[i-1].mode_no[1] == 0x56 ||
+                                  sisbios_mode[i-1].mode_no[1] == 0x53)
+                                       continue;
+                       } else {
+                               if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+                                  sisbios_mode[i-1].mode_no[1] == 0x5b)
+                                       continue;
+                       }
+                       sisfb_mode_idx = i - 1;
+                       j = 1;
+                       break;
+               }
+       }
+
+       if((!j) && !quiet)
+               printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
 }
 
 #ifndef MODULE
@@ -265,7 +276,7 @@ static void __devinit
 sisfb_get_vga_mode_from_kernel(void)
 {
 #if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
-       char mymode[32];
+       char mymode[32];
        int  mydepth = screen_info.lfb_depth;
 
        if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
@@ -274,15 +285,17 @@ sisfb_get_vga_mode_from_kernel(void)
            (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
            (mydepth >= 8) && (mydepth <= 32) ) {
 
-           if(mydepth == 24) mydepth = 32;
+               if(mydepth == 24) mydepth = 32;
 
-           sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
-                                       screen_info.lfb_height,
+               sprintf(mymode, "%ux%ux%u", screen_info.lfb_width,
+                                       screen_info.lfb_height,
                                        mydepth);
 
-           printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
+               printk(KERN_DEBUG
+                       "sisfb: Using vga mode %s pre-set by kernel as default\n",
+                       mymode);
 
-           sisfb_search_mode(mymode, TRUE);
+               sisfb_search_mode(mymode, TRUE);
        }
 #endif
        return;
@@ -294,26 +307,25 @@ sisfb_search_crt2type(const char *name)
 {
        int i = 0;
 
-       /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+       /* We don't know the hardware specs yet and there is no ivideo */
 
        if(name == NULL) return;
 
        while(sis_crt2type[i].type_no != -1) {
-               if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
-                       sisfb_crt2type = sis_crt2type[i].type_no;
-                       sisfb_tvplug = sis_crt2type[i].tvplug_no;
-                       sisfb_crt2flags = sis_crt2type[i].flags;
-                       break;
-               }
-               i++;
+               if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+                       sisfb_crt2type = sis_crt2type[i].type_no;
+                       sisfb_tvplug = sis_crt2type[i].tvplug_no;
+                       sisfb_crt2flags = sis_crt2type[i].flags;
+                       break;
+               }
+               i++;
        }
 
        sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
        sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
 
-       if(sisfb_crt2type < 0) {
+       if(sisfb_crt2type < 0)
                printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
-       }
 }
 
 static void __init
@@ -321,16 +333,17 @@ sisfb_search_tvstd(const char *name)
 {
        int i = 0;
 
-       /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+       /* We don't know the hardware specs yet and there is no ivideo */
 
-       if(name == NULL) return;
+       if(name == NULL)
+               return;
 
        while(sis_tvtype[i].type_no != -1) {
-               if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
-                       sisfb_tvstd = sis_tvtype[i].type_no;
-                       break;
-               }
-               i++;
+               if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+                       sisfb_tvstd = sis_tvtype[i].type_no;
+                       break;
+               }
+               i++;
        }
 }
 
@@ -340,38 +353,101 @@ sisfb_search_specialtiming(const char *name)
        int i = 0;
        BOOLEAN found = FALSE;
 
-       /* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+       /* We don't know the hardware specs yet and there is no ivideo */
 
-       if(name == NULL) return;
+       if(name == NULL)
+               return;
 
        if(!strnicmp(name, "none", 4)) {
-               sisfb_specialtiming = CUT_FORCENONE;
+               sisfb_specialtiming = CUT_FORCENONE;
                printk(KERN_DEBUG "sisfb: Special timing disabled\n");
        } else {
-          while(mycustomttable[i].chipID != 0) {
-             if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
-                sisfb_specialtiming = mycustomttable[i].SpecialID;
-                found = TRUE;
-                printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
-                       mycustomttable[i].vendorName, mycustomttable[i].cardName,
-                       mycustomttable[i].optionName);
-                break;
-             }
-             i++;
-          }
-          if(!found) {
-             printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
-             printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
-             i = 0;
-             while(mycustomttable[i].chipID != 0) {
-                printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
-                    mycustomttable[i].optionName,
-                    mycustomttable[i].vendorName,
-                    mycustomttable[i].cardName);
-                i++;
-             }
-           }
-       }
+               while(mycustomttable[i].chipID != 0) {
+                       if(!strnicmp(name,mycustomttable[i].optionName,
+                          strlen(mycustomttable[i].optionName))) {
+                               sisfb_specialtiming = mycustomttable[i].SpecialID;
+                               found = TRUE;
+                               printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+                                       mycustomttable[i].vendorName,
+                                       mycustomttable[i].cardName,
+                                       mycustomttable[i].optionName);
+                               break;
+                       }
+                       i++;
+               }
+               if(!found) {
+                       printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+                       printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+                       i = 0;
+                       while(mycustomttable[i].chipID != 0) {
+                               printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+                                       mycustomttable[i].optionName,
+                                       mycustomttable[i].vendorName,
+                                       mycustomttable[i].cardName);
+                               i++;
+                       }
+               }
+       }
+}
+
+/* ----------- Various detection routines ----------- */
+
+static void __devinit
+sisfb_detect_custom_timing(struct sis_video_info *ivideo)
+{
+       unsigned char *biosver = NULL;
+       unsigned char *biosdate = NULL;
+       BOOLEAN footprint;
+       u32 chksum = 0;
+       int i, j;
+
+       if(ivideo->SiS_Pr.UseROM) {
+               biosver = ivideo->SiS_Pr.VirtualRomBase + 0x06;
+               biosdate = ivideo->SiS_Pr.VirtualRomBase + 0x2c;
+               for(i = 0; i < 32768; i++)
+                       chksum += ivideo->SiS_Pr.VirtualRomBase[i];
+       }
+
+       i = 0;
+       do {
+               if( (mycustomttable[i].chipID == ivideo->chip)                  &&
+                   ((!strlen(mycustomttable[i].biosversion)) ||
+                    (ivideo->SiS_Pr.UseROM &&
+                     (!strncmp(mycustomttable[i].biosversion, biosver,
+                               strlen(mycustomttable[i].biosversion)))))       &&
+                   ((!strlen(mycustomttable[i].biosdate)) ||
+                    (ivideo->SiS_Pr.UseROM &&
+                     (!strncmp(mycustomttable[i].biosdate, biosdate,
+                               strlen(mycustomttable[i].biosdate)))))          &&
+                   ((!mycustomttable[i].bioschksum) ||
+                    (ivideo->SiS_Pr.UseROM &&
+                     (mycustomttable[i].bioschksum == chksum)))                &&
+                   (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+                   (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
+                       footprint = TRUE;
+                       for(j = 0; j < 5; j++) {
+                               if(mycustomttable[i].biosFootprintAddr[j]) {
+                                       if(ivideo->SiS_Pr.UseROM) {
+                                               if(ivideo->SiS_Pr.VirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+                                                       mycustomttable[i].biosFootprintData[j]) {
+                                                       footprint = FALSE;
+                                               }
+                                       } else
+                                               footprint = FALSE;
+                               }
+                       }
+                       if(footprint) {
+                               ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+                               printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
+                                       mycustomttable[i].vendorName,
+                               mycustomttable[i].cardName);
+                               printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
+                                       mycustomttable[i].optionName);
+                               break;
+                       }
+               }
+               i++;
+       } while(mycustomttable[i].chipID);
 }
 
 static BOOLEAN __devinit
@@ -384,22 +460,23 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
           buffer[2] != 0xff || buffer[3] != 0xff ||
           buffer[4] != 0xff || buffer[5] != 0xff ||
           buffer[6] != 0xff || buffer[7] != 0x00) {
-          printk(KERN_DEBUG "sisfb: Bad EDID header\n");
-          return FALSE;
+               printk(KERN_DEBUG "sisfb: Bad EDID header\n");
+               return FALSE;
        }
 
        if(buffer[0x12] != 0x01) {
-          printk(KERN_INFO "sisfb: EDID version %d not supported\n",
-               buffer[0x12]);
-          return FALSE;
+               printk(KERN_INFO "sisfb: EDID version %d not supported\n",
+                       buffer[0x12]);
+               return FALSE;
        }
 
        monitor->feature = buffer[0x18];
 
        if(!buffer[0x14] & 0x80) {
-          if(!(buffer[0x14] & 0x08)) {
-             printk(KERN_INFO "sisfb: WARNING: Monitor does not support separate syncs\n");
-          }
+               if(!(buffer[0x14] & 0x08)) {
+                       printk(KERN_INFO
+                               "sisfb: WARNING: Monitor does not support separate syncs\n");
+               }
        }
 
        if(buffer[0x13] >= 0x01) {
@@ -409,7 +486,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
            j = 0x36;
            for(i=0; i<4; i++) {
               if(buffer[j]     == 0x00 && buffer[j + 1] == 0x00 &&
-                 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
+                 buffer[j + 2] == 0x00 && buffer[j + 3] == 0xfd &&
                  buffer[j + 4] == 0x00) {
                  monitor->hmin = buffer[j + 7];
                  monitor->hmax = buffer[j + 8];
@@ -435,7 +512,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
           emodes = buffer[0x23] | (buffer[0x24] << 8) | (buffer[0x25] << 16);
           for(i = 0; i < 13; i++) {
              if(emodes & sisfb_ddcsmodes[i].mask) {
-                if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
+                if(monitor->hmin > sisfb_ddcsmodes[i].h) monitor->hmin = sisfb_ddcsmodes[i].h;
                 if(monitor->hmax < sisfb_ddcsmodes[i].h) monitor->hmax = sisfb_ddcsmodes[i].h + 1;
                 if(monitor->vmin > sisfb_ddcsmodes[i].v) monitor->vmin = sisfb_ddcsmodes[i].v;
                 if(monitor->vmax < sisfb_ddcsmodes[i].v) monitor->vmax = sisfb_ddcsmodes[i].v;
@@ -446,80 +523,81 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
           for(i = 0; i < 8; i++) {
              xres = (buffer[index] + 31) * 8;
              switch(buffer[index + 1] & 0xc0) {
-                case 0xc0: yres = (xres * 9) / 16; break;
-                case 0x80: yres = (xres * 4) /  5; break;
-                case 0x40: yres = (xres * 3) /  4; break;
-                default:   yres = xres;            break;
+                case 0xc0: yres = (xres * 9) / 16; break;
+                case 0x80: yres = (xres * 4) /  5; break;
+                case 0x40: yres = (xres * 3) /  4; break;
+                default:   yres = xres;            break;
              }
              refresh = (buffer[index + 1] & 0x3f) + 60;
              if((xres >= 640) && (yres >= 480)) {
-                 for(j = 0; j < 8; j++) {
-                   if((xres == sisfb_ddcfmodes[j].x) &&
-                      (yres == sisfb_ddcfmodes[j].y) &&
+                for(j = 0; j < 8; j++) {
+                   if((xres == sisfb_ddcfmodes[j].x) &&
+                      (yres == sisfb_ddcfmodes[j].y) &&
                       (refresh == sisfb_ddcfmodes[j].v)) {
                      if(monitor->hmin > sisfb_ddcfmodes[j].h) monitor->hmin = sisfb_ddcfmodes[j].h;
                      if(monitor->hmax < sisfb_ddcfmodes[j].h) monitor->hmax = sisfb_ddcfmodes[j].h + 1;
                      if(monitor->vmin > sisfb_ddcsmodes[j].v) monitor->vmin = sisfb_ddcsmodes[j].v;
                      if(monitor->vmax < sisfb_ddcsmodes[j].v) monitor->vmax = sisfb_ddcsmodes[j].v;
-                     if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[i].d;
-                   }
-                }
+                     if(monitor->dclockmax < sisfb_ddcsmodes[j].d) monitor->dclockmax = sisfb_ddcsmodes[j].d;
+                   }
+                }
              }
              index += 2;
-           }
+          }
           if((monitor->hmin <= monitor->hmax) && (monitor->vmin <= monitor->vmax)) {
              monitor->datavalid = TRUE;
           }
        }
 
-       return(monitor->datavalid);
+       return monitor->datavalid;
 }
 
 static void __devinit
 sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
 {
-       USHORT  temp, i, realcrtno = crtno;
-       u8      buffer[256];
+       unsigned short temp, i, realcrtno = crtno;
+       unsigned char  buffer[256];
 
        monitor->datavalid = FALSE;
 
        if(crtno) {
-                  if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
-          else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
-          else return;
-       }
+          if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
+          else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
+          else return;
+       }
 
-       if((ivideo->sisfb_crt1off) && (!crtno)) return;
+       if((ivideo->sisfb_crt1off) && (!crtno))
+               return;
 
-       temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
-                               realcrtno, 0, &buffer[0]);
-       if((!temp) || (temp == 0xffff)) {
-          printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
+       temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+                               realcrtno, 0, &buffer[0], ivideo->vbflags2);
+       if((!temp) || (temp == 0xffff)) {
+          printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
           return;
-       } else {
-          printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
-          printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
-               crtno + 1,
-               (temp & 0x1a) ? "" : "[none of the supported]",
-               (temp & 0x02) ? "2 " : "",
-               (temp & 0x08) ? "D&P" : "",
-               (temp & 0x10) ? "FPDI-2" : "");
-          if(temp & 0x02) {
+       } else {
+          printk(KERN_INFO "sisfb: CRT%d DDC supported\n", crtno + 1);
+          printk(KERN_INFO "sisfb: CRT%d DDC level: %s%s%s%s\n",
+               crtno + 1,
+               (temp & 0x1a) ? "" : "[none of the supported]",
+               (temp & 0x02) ? "2 " : "",
+               (temp & 0x08) ? "D&P" : "",
+               (temp & 0x10) ? "FPDI-2" : "");
+          if(temp & 0x02) {
              i = 3;  /* Number of retrys */
              do {
-                temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
-                                    realcrtno, 1, &buffer[0]);
+                temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+                                    realcrtno, 1, &buffer[0], ivideo->vbflags2);
              } while((temp) && i--);
-              if(!temp) {
-                if(sisfb_interpret_edid(monitor, &buffer[0])) {
+             if(!temp) {
+                if(sisfb_interpret_edid(monitor, &buffer[0])) {
                    printk(KERN_INFO "sisfb: Monitor range H %d-%dKHz, V %d-%dHz, Max. dotclock %dMHz\n",
-                       monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
+                       monitor->hmin, monitor->hmax, monitor->vmin, monitor->vmax,
                        monitor->dclockmax / 1000);
                 } else {
-                   printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
-                }
+                   printk(KERN_INFO "sisfb: CRT%d DDC EDID corrupt\n", crtno + 1);
+                }
              } else {
-                printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
+                printk(KERN_INFO "sisfb: CRT%d DDC reading failed\n", crtno + 1);
              }
           } else {
              printk(KERN_INFO "sisfb: VESA D&P and FPDI-2 not supported yet\n");
@@ -527,6 +605,8 @@ sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, i
        }
 }
 
+/* -------------- Mode validation --------------- */
+
 static BOOLEAN
 sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
                int mode_idx, int rate_idx, int rate)
@@ -534,42 +614,49 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
        int htotal, vtotal;
        unsigned int dclock, hsync;
 
-       if(!monitor->datavalid) return TRUE;
+       if(!monitor->datavalid)
+               return TRUE;
 
-       if(mode_idx < 0) return FALSE;
+       if(mode_idx < 0)
+               return FALSE;
 
        /* Skip for 320x200, 320x240, 640x400 */
-       switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
-       case 0x59:
-       case 0x41:
-       case 0x4f:
-       case 0x50:
-       case 0x56:
-       case 0x53:
-       case 0x2f:
-       case 0x5d:
-       case 0x5e:
-               return TRUE;
+       switch(sisbios_mode[mode_idx].mode_no[ivideo->mni]) {
+       case 0x59:
+       case 0x41:
+       case 0x4f:
+       case 0x50:
+       case 0x56:
+       case 0x53:
+       case 0x2f:
+       case 0x5d:
+       case 0x5e:
+               return TRUE;
 #ifdef CONFIG_FB_SIS_315
        case 0x5a:
        case 0x5b:
                if(ivideo->sisvga_engine == SIS_315_VGA) return TRUE;
 #endif
-       }
+       }
 
-       if(rate < (monitor->vmin - 1)) return FALSE;
-       if(rate > (monitor->vmax + 1)) return FALSE;
+       if(rate < (monitor->vmin - 1))
+               return FALSE;
+       if(rate > (monitor->vmax + 1))
+               return FALSE;
 
-       if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+       if(sisfb_gettotalfrommode(&ivideo->SiS_Pr,
                                  sisbios_mode[mode_idx].mode_no[ivideo->mni],
-                                 &htotal, &vtotal, rate_idx)) {
+                                 &htotal, &vtotal, rate_idx)) {
                dclock = (htotal * vtotal * rate) / 1000;
-               if(dclock > (monitor->dclockmax + 1000)) return FALSE;
+               if(dclock > (monitor->dclockmax + 1000))
+                       return FALSE;
                hsync = dclock / htotal;
-               if(hsync < (monitor->hmin - 1)) return FALSE;
-               if(hsync > (monitor->hmax + 1)) return FALSE;
+               if(hsync < (monitor->hmin - 1))
+                       return FALSE;
+               if(hsync > (monitor->hmax + 1))
+                       return FALSE;
         } else {
-               return FALSE;
+               return FALSE;
        }
        return TRUE;
 }
@@ -577,82 +664,79 @@ sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor,
 static int
 sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
 {
-   u16 xres=0, yres, myres;
+       u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-   if(ivideo->sisvga_engine == SIS_300_VGA) {
-      if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
-   }
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
+               if(!(sisbios_mode[myindex].chipset & MD_SIS300))
+                       return -1 ;
+       }
 #endif
 #ifdef CONFIG_FB_SIS_315
-   if(ivideo->sisvga_engine == SIS_315_VGA) {
-      if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
-   }
+       if(ivideo->sisvga_engine == SIS_315_VGA) {
+               if(!(sisbios_mode[myindex].chipset & MD_SIS315))
+                       return -1;
+       }
 #endif
 
-   myres = sisbios_mode[myindex].yres;
+       myres = sisbios_mode[myindex].yres;
 
-   switch(vbflags & VB_DISPTYPE_DISP2) {
+       switch(vbflags & VB_DISPTYPE_DISP2) {
 
-     case CRT2_LCD:
+       case CRT2_LCD:
+               xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 
-        xres = ivideo->lcdxres; yres = ivideo->lcdyres;
-
-       if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
-               if(sisbios_mode[myindex].xres > xres) return(-1);
-               if(myres > yres) return(-1);
-       }
+               if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
+                  (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
+                       if(sisbios_mode[myindex].xres > xres)
+                               return -1;
+                       if(myres > yres)
+                               return -1;
+               }
 
-       if(vbflags & (VB_LVDS | VB_30xBDH)) {
-          if(sisbios_mode[myindex].xres == 320) {
-             if((myres == 240) || (myres == 480)) {
-                if(!ivideo->sisfb_fstn) {
-                   if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
-                      sisbios_mode[myindex].mode_no[1] == 0x5b)
-                      return(-1);
-                } else {
-                   if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
-                      sisbios_mode[myindex].mode_no[1] == 0x56 ||
-                      sisbios_mode[myindex].mode_no[1] == 0x53)
-                      return(-1);
-                }
-             }
-          }
-       }
+               if(ivideo->sisfb_fstn) {
+                       if(sisbios_mode[myindex].xres == 320) {
+                               if(myres == 240) {
+                                       switch(sisbios_mode[myindex].mode_no[1]) {
+                                               case 0x50: myindex = MODE_FSTN_8;  break;
+                                               case 0x56: myindex = MODE_FSTN_16; break;
+                                               case 0x53: return -1;
+                                       }
+                               }
+                       }
+               }
 
-       if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-                            sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
-                            ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
-               return(-1);
-       }
-       break;
+               if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+                               sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
+                               ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
+                       return -1;
+               }
+               break;
 
-     case CRT2_TV:
-       if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-                           sisbios_mode[myindex].yres, 0) < 0x14) {
-               return(-1);
-       }
-       break;
+       case CRT2_TV:
+               if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+                               sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+                       return -1;
+               }
+               break;
 
-     case CRT2_VGA:
-        if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-                             sisbios_mode[myindex].yres, 0) < 0x14) {
-               return(-1);
+       case CRT2_VGA:
+               if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+                               sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
+                       return -1;
+               }
+               break;
        }
-       break;
-     }
 
-     return(myindex);
+       return myindex;
 }
 
 static u8
 sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
 {
-       u16 xres, yres;
        int i = 0;
-
-       xres = sisbios_mode[mode_idx].xres;
-       yres = sisbios_mode[mode_idx].yres;
+       u16 xres = sisbios_mode[mode_idx].xres;
+       u16 yres = sisbios_mode[mode_idx].yres;
 
        ivideo->rate_idx = 0;
        while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
@@ -672,14 +756,14 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
                                                rate, sisfb_vrate[i-1].refresh);
                                        ivideo->rate_idx = sisfb_vrate[i-1].idx;
                                        ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
-                               } 
+                               }
                                break;
                        } else if((rate - sisfb_vrate[i].refresh) <= 2) {
                                DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
                                                rate, sisfb_vrate[i].refresh);
-                               ivideo->rate_idx = sisfb_vrate[i].idx;
-                               break;
-                       }
+                               ivideo->rate_idx = sisfb_vrate[i].idx;
+                               break;
+                       }
                }
                i++;
        }
@@ -695,252 +779,321 @@ sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int
 static BOOLEAN
 sisfb_bridgeisslave(struct sis_video_info *ivideo)
 {
-   unsigned char P1_00;
+       unsigned char P1_00;
 
-   if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
+       if(!(ivideo->vbflags2 & VB2_VIDEOBRIDGE))
+               return FALSE;
 
-   inSISIDXREG(SISPART1,0x00,P1_00);
-   if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-       ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
-          return TRUE;
-   } else {
-           return FALSE;
-   }
+       inSISIDXREG(SISPART1,0x00,P1_00);
+       if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+           ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+               return TRUE;
+       } else {
+               return FALSE;
+       }
 }
 
 static BOOLEAN
 sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
-   u8 temp;
+       u8 temp;
 
-   inSISIDXREG(SISCR,0x17,temp);
-   if(!(temp & 0x80)) return FALSE;
+       inSISIDXREG(SISCR,0x17,temp);
+       if(!(temp & 0x80))
+               return FALSE;
 
-   inSISIDXREG(SISSR,0x1f,temp);
-   if(temp & 0xc0) return FALSE;
+       inSISIDXREG(SISSR,0x1f,temp);
+       if(temp & 0xc0)
+               return FALSE;
 
-   return TRUE;
+       return TRUE;
 }
 
 static BOOLEAN
 sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 {
-   if(!sisfballowretracecrt1(ivideo)) return FALSE;
+       if(!sisfballowretracecrt1(ivideo))
+               return FALSE;
 
-   if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
-   else                           return FALSE;
+       if(inSISREG(SISINPSTAT) & 0x08)
+               return TRUE;
+       else
+               return FALSE;
 }
 
 static void
 sisfbwaitretracecrt1(struct sis_video_info *ivideo)
 {
-   int watchdog;
+       int watchdog;
 
-   if(!sisfballowretracecrt1(ivideo)) return;
+       if(!sisfballowretracecrt1(ivideo))
+               return;
 
-   watchdog = 65536;
-   while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
-   watchdog = 65536;
-   while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
+       watchdog = 65536;
+       while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
+       watchdog = 65536;
+       while((inSISREG(SISINPSTAT) & 0x08) && --watchdog);
 }
 
 static BOOLEAN
 sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 {
-   unsigned char temp, reg;
+       unsigned char temp, reg;
 
-   switch(ivideo->sisvga_engine) {
-   case SIS_300_VGA: reg = 0x25; break;
-   case SIS_315_VGA: reg = 0x30; break;
-   default:          return FALSE;
-   }
+       switch(ivideo->sisvga_engine) {
+       case SIS_300_VGA: reg = 0x25; break;
+       case SIS_315_VGA: reg = 0x30; break;
+       default:          return FALSE;
+       }
 
-   inSISIDXREG(SISPART1, reg, temp);
-   if(temp & 0x02) return TRUE;
-   else           return FALSE;
+       inSISIDXREG(SISPART1, reg, temp);
+       if(temp & 0x02)
+               return TRUE;
+       else
+               return FALSE;
 }
 
 static BOOLEAN
 sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 {
-   if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-      if(sisfb_bridgeisslave(ivideo)) {
-         return(sisfbcheckvretracecrt1(ivideo));
-      } else {
-         return(sisfbcheckvretracecrt2(ivideo));
-      }
-   } 
-   return(sisfbcheckvretracecrt1(ivideo));
+       if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+               if(!sisfb_bridgeisslave(ivideo)) {
+                       return sisfbcheckvretracecrt2(ivideo);
+               }
+       }
+       return sisfbcheckvretracecrt1(ivideo);
 }
 
 static u32
 sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
 {
-   u8 idx, reg1, reg2, reg3, reg4;
-   u32 ret = 0;
-
-   (*vcount) = (*hcount) = 0;
-
-   if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
-      ret |= (FB_VBLANK_HAVE_VSYNC  |
-             FB_VBLANK_HAVE_HBLANK |
-              FB_VBLANK_HAVE_VBLANK |
-             FB_VBLANK_HAVE_VCOUNT |
-             FB_VBLANK_HAVE_HCOUNT);
-      switch(ivideo->sisvga_engine) {
-         case SIS_300_VGA: idx = 0x25; break;
-        default:
-         case SIS_315_VGA: idx = 0x30; break;
-      }
-      inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
-      inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
-      inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
-      inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
-      if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
-      if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
-      if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
-      (*vcount) = reg3 | ((reg4 & 0x70) << 4);
-      (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
-   } else if(sisfballowretracecrt1(ivideo)) {
-      ret |= (FB_VBLANK_HAVE_VSYNC  |
-              FB_VBLANK_HAVE_VBLANK |
-             FB_VBLANK_HAVE_VCOUNT |
-             FB_VBLANK_HAVE_HCOUNT);
-      reg1 = inSISREG(SISINPSTAT);
-      if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
-      if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
-      inSISIDXREG(SISCR,0x20,reg1);
-      inSISIDXREG(SISCR,0x1b,reg1);
-      inSISIDXREG(SISCR,0x1c,reg2);
-      inSISIDXREG(SISCR,0x1d,reg3);
-      (*vcount) = reg2 | ((reg3 & 0x07) << 8);
-      (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
-   }
-   return ret;
+       u8 idx, reg1, reg2, reg3, reg4;
+       u32 ret = 0;
+
+       (*vcount) = (*hcount) = 0;
+
+       if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+
+               ret |= (FB_VBLANK_HAVE_VSYNC  |
+                       FB_VBLANK_HAVE_HBLANK |
+                       FB_VBLANK_HAVE_VBLANK |
+                       FB_VBLANK_HAVE_VCOUNT |
+                       FB_VBLANK_HAVE_HCOUNT);
+               switch(ivideo->sisvga_engine) {
+                       case SIS_300_VGA: idx = 0x25; break;
+                       default:
+                       case SIS_315_VGA: idx = 0x30; break;
+               }
+               inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
+               inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
+               inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
+               inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+               if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+               if(reg1 & 0x02) ret |= FB_VBLANK_VSYNCING;
+               if(reg4 & 0x80) ret |= FB_VBLANK_HBLANKING;
+               (*vcount) = reg3 | ((reg4 & 0x70) << 4);
+               (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+
+       } else if(sisfballowretracecrt1(ivideo)) {
+
+               ret |= (FB_VBLANK_HAVE_VSYNC  |
+                       FB_VBLANK_HAVE_VBLANK |
+                       FB_VBLANK_HAVE_VCOUNT |
+                       FB_VBLANK_HAVE_HCOUNT);
+               reg1 = inSISREG(SISINPSTAT);
+               if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+               if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+               inSISIDXREG(SISCR,0x20,reg1);
+               inSISIDXREG(SISCR,0x1b,reg1);
+               inSISIDXREG(SISCR,0x1c,reg2);
+               inSISIDXREG(SISCR,0x1d,reg3);
+               (*vcount) = reg2 | ((reg3 & 0x07) << 8);
+               (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+       }
+
+       return ret;
 }
 
 static int
 sisfb_myblank(struct sis_video_info *ivideo, int blank)
 {
-   u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
-   BOOLEAN backlight = TRUE;
-
-   switch(blank) {
-   case FB_BLANK_UNBLANK:      /* on */
-      sr01  = 0x00;
-      sr11  = 0x00;
-      sr1f  = 0x00;
-      cr63  = 0x00;
-      p2_0  = 0x20;
-      p1_13 = 0x00;
-      backlight = TRUE;
-      break;
-   case FB_BLANK_NORMAL:       /* blank */
-      sr01  = 0x20;
-      sr11  = 0x00;
-      sr1f  = 0x00;
-      cr63  = 0x00;
-      p2_0  = 0x20;
-      p1_13 = 0x00;
-      backlight = TRUE;
-      break;
-   case FB_BLANK_VSYNC_SUSPEND:        /* no vsync */
-      sr01  = 0x20;
-      sr11  = 0x08;
-      sr1f  = 0x80;
-      cr63  = 0x40;
-      p2_0  = 0x40;
-      p1_13 = 0x80;
-      backlight = FALSE;
-      break;
-   case FB_BLANK_HSYNC_SUSPEND:        /* no hsync */
-      sr01  = 0x20;
-      sr11  = 0x08;
-      sr1f  = 0x40;
-      cr63  = 0x40;
-      p2_0  = 0x80;
-      p1_13 = 0x40;
-      backlight = FALSE;
-      break;
-   case FB_BLANK_POWERDOWN:    /* off */
-      sr01  = 0x20;
-      sr11  = 0x08;
-      sr1f  = 0xc0;
-      cr63  = 0x40;
-      p2_0  = 0xc0;
-      p1_13 = 0xc0;
-      backlight = FALSE;
-      break;
-   default:
-      return 1;
-   }
-
-   if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
-
-      if( (!ivideo->sisfb_thismonitor.datavalid) ||
-          ((ivideo->sisfb_thismonitor.datavalid) &&
-           (ivideo->sisfb_thismonitor.feature & 0xe0))) {
-
-        if(ivideo->sisvga_engine == SIS_315_VGA) {
-           setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
-        }
-
-        if(!(sisfb_bridgeisslave(ivideo))) {
-           setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
-           setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
-        }
-      }
-
-   }
-
-   if(ivideo->currentvbflags & CRT2_LCD) {
-
-      if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
-        if(backlight) {
-           SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
-        } else {
-           SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
-        }
-      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
-        if(ivideo->vbflags & VB_CHRONTEL) {
-           if(backlight) {
-              SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
-           } else {
-              SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
-           }
-        }
-      }
-
-      if(((ivideo->sisvga_engine == SIS_300_VGA) &&
-          (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
-         ((ivideo->sisvga_engine == SIS_315_VGA) &&
-          ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
-          setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
-      }
-
-      if(ivideo->sisvga_engine == SIS_300_VGA) {
-         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo->vbflags & VB_30xBDH))) {
-           setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
-        }
-      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
-         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo->vbflags & VB_30xBDH))) {
-           setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
-        }
-      }
-
-   } else if(ivideo->currentvbflags & CRT2_VGA) {
-
-      if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
-         setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
-      }
-
-   }
-
-   return(0);
+       u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
+       BOOLEAN backlight = TRUE;
+
+       switch(blank) {
+               case FB_BLANK_UNBLANK:  /* on */
+                       sr01  = 0x00;
+                       sr11  = 0x00;
+                       sr1f  = 0x00;
+                       cr63  = 0x00;
+                       p2_0  = 0x20;
+                       p1_13 = 0x00;
+                       backlight = TRUE;
+                       break;
+               case FB_BLANK_NORMAL:   /* blank */
+                       sr01  = 0x20;
+                       sr11  = 0x00;
+                       sr1f  = 0x00;
+                       cr63  = 0x00;
+                       p2_0  = 0x20;
+                       p1_13 = 0x00;
+                       backlight = TRUE;
+                       break;
+               case FB_BLANK_VSYNC_SUSPEND:    /* no vsync */
+                       sr01  = 0x20;
+                       sr11  = 0x08;
+                       sr1f  = 0x80;
+                       cr63  = 0x40;
+                       p2_0  = 0x40;
+                       p1_13 = 0x80;
+                       backlight = FALSE;
+                       break;
+               case FB_BLANK_HSYNC_SUSPEND:    /* no hsync */
+                       sr01  = 0x20;
+                       sr11  = 0x08;
+                       sr1f  = 0x40;
+                       cr63  = 0x40;
+                       p2_0  = 0x80;
+                       p1_13 = 0x40;
+                       backlight = FALSE;
+                       break;
+               case FB_BLANK_POWERDOWN:        /* off */
+                       sr01  = 0x20;
+                       sr11  = 0x08;
+                       sr1f  = 0xc0;
+                       cr63  = 0x40;
+                       p2_0  = 0xc0;
+                       p1_13 = 0xc0;
+                       backlight = FALSE;
+                       break;
+               default:
+                       return 1;
+       }
+
+       if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
+
+               if( (!ivideo->sisfb_thismonitor.datavalid) ||
+                   ((ivideo->sisfb_thismonitor.datavalid) &&
+                    (ivideo->sisfb_thismonitor.feature & 0xe0))) {
+
+                       if(ivideo->sisvga_engine == SIS_315_VGA) {
+                               setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+                       }
+
+                       if(!(sisfb_bridgeisslave(ivideo))) {
+                               setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+                               setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+                       }
+               }
+
+       }
+
+       if(ivideo->currentvbflags & CRT2_LCD) {
+
+               if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+                       if(backlight) {
+                               SiS_SiS30xBLOn(&ivideo->SiS_Pr);
+                       } else {
+                               SiS_SiS30xBLOff(&ivideo->SiS_Pr);
+                       }
+               } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+#ifdef CONFIG_FB_SIS_315
+                       if(ivideo->vbflags2 & VB2_CHRONTEL) {
+                               if(backlight) {
+                                       SiS_Chrontel701xBLOn(&ivideo->SiS_Pr);
+                               } else {
+                                       SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
+                               }
+                       }
+#endif
+               }
+
+               if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+                   (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) ||
+                  ((ivideo->sisvga_engine == SIS_315_VGA) &&
+                   ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) {
+                       setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
+               }
+
+               if(ivideo->sisvga_engine == SIS_300_VGA) {
+                       if((ivideo->vbflags2 & VB2_30xB) &&
+                          (!(ivideo->vbflags2 & VB2_30xBDH))) {
+                               setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
+                       }
+               } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+                       if((ivideo->vbflags2 & VB2_30xB) &&
+                          (!(ivideo->vbflags2 & VB2_30xBDH))) {
+                               setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+                       }
+               }
+
+       } else if(ivideo->currentvbflags & CRT2_VGA) {
+
+               if(ivideo->vbflags2 & VB2_30xB) {
+                       setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
+               }
+
+       }
+
+       return 0;
+}
+
+/* ------------- Callbacks from init.c/init301.c  -------------- */
+
+#ifdef CONFIG_FB_SIS_300
+unsigned int
+sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+   u32 val = 0;
+
+   pci_read_config_dword(ivideo->nbridge, reg, &val);
+   return (unsigned int)val;
+}
+
+void
+sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+   pci_write_config_dword(ivideo->nbridge, reg, (u32)val);
+}
+
+unsigned int
+sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+   u32 val = 0;
+
+   if(!ivideo->lpcdev) return 0;
+
+   pci_read_config_dword(ivideo->lpcdev, reg, &val);
+   return (unsigned int)val;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+void
+sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+
+   pci_write_config_byte(ivideo->nbridge, reg, (u8)val);
 }
 
+unsigned int
+sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg)
+{
+   struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo;
+   u16 val = 0;
+
+   if(!ivideo->lpcdev) return 0;
+
+   pci_read_config_word(ivideo->lpcdev, reg, &val);
+   return (unsigned int)val;
+}
+#endif
+
 /* ----------- FBDev related routines for all series ----------- */
 
 static int
@@ -952,7 +1105,7 @@ sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
 static void
 sisfb_set_vparms(struct sis_video_info *ivideo)
 {
-       switch(ivideo->video_bpp) {
+       switch(ivideo->video_bpp) {
        case 8:
                ivideo->DstColor = 0x0000;
                ivideo->SiS310_AccelDepth = 0x00000000;
@@ -972,14 +1125,13 @@ sisfb_set_vparms(struct sis_video_info *ivideo)
                ivideo->video_cmap_len = 16;
                printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
                ivideo->accel = 0;
-               break;
-       }
+       }
 }
 
 static int
 sisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
-       int maxyres = ivideo->heapstart / (var->xres_virtual * (var->bits_per_pixel >> 3));
+       int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3));
 
        if(maxyres > 32767) maxyres = 32767;
 
@@ -996,30 +1148,29 @@ sisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
                        ivideo->scrnpitchCRT1 <<= 1;
                }
        }
-
 }
 
 static void
 sisfb_set_pitch(struct sis_video_info *ivideo)
 {
-       BOOLEAN isslavemode = FALSE;
+       BOOLEAN isslavemode = FALSE;
        unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3;
        unsigned short HDisplay2 = ivideo->video_linelength >> 3;
 
-       if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
+       if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE;
 
-       /* We need to set pitch for CRT1 if bridge is in slave mode, too */
-       if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
-               outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
-               setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
+       /* We need to set pitch for CRT1 if bridge is in slave mode, too */
+       if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) {
+               outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF));
+               setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8));
        }
 
-       /* We must not set the pitch for CRT2 if bridge is in slave mode */
-       if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
+       /* We must not set the pitch for CRT2 if bridge is in slave mode */
+       if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) {
                orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01);
-               outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
-               setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
-       }
+               outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF));
+               setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8));
+       }
 }
 
 static void
@@ -1055,13 +1206,42 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
        }
 }
 
+static int
+sisfb_set_mode(struct sis_video_info *ivideo, int clrscrn)
+{
+       unsigned short modeno = ivideo->mode_no;
+
+       /* >=2.6.12's fbcon clears the screen anyway */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
+       if(!clrscrn) modeno |= 0x80;
+#else
+       modeno |= 0x80;
+#endif
+
+       outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+       sisfb_pre_setmode(ivideo);
+
+       if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 0) {
+               printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
+               return -EINVAL;
+       }
+
+       outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+
+       sisfb_post_setmode(ivideo);
+
+       return 0;
+}
+
+
 static int
 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info)
 {
        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
        unsigned int htotal = 0, vtotal = 0;
        unsigned int drate = 0, hrate = 0;
-       int found_mode = 0;
+       int found_mode = 0, ret;
        int old_mode;
        u32 pixclock;
 
@@ -1088,11 +1268,11 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
        }
 
        if(pixclock && htotal && vtotal) {
-               drate = 1000000000 / pixclock;
-               hrate = (drate * 1000) / htotal;
-               ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+               drate = 1000000000 / pixclock;
+               hrate = (drate * 1000) / htotal;
+               ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
        } else {
-               ivideo->refresh_rate = 60;
+               ivideo->refresh_rate = 60;
        }
 
        old_mode = ivideo->sisfb_mode_idx;
@@ -1113,6 +1293,7 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
        if(found_mode) {
                ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
                                ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+               ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
        } else {
                ivideo->sisfb_mode_idx = -1;
        }
@@ -1131,10 +1312,10 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        if(ivideo->sisfb_thismonitor.datavalid) {
-          if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+               if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
                                 ivideo->rate_idx, ivideo->refresh_rate)) {
-             printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
-          }
+                       printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+               }
        }
 #endif
 
@@ -1143,24 +1324,9 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
 #else
        if(isactive) {
 #endif
-               sisfb_pre_setmode(ivideo);
-
-               if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
-                       printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
-                       return -EINVAL;
-               }
-
-               outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-
-               sisfb_post_setmode(ivideo);
-
-               ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
-               ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
-               ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
-
-               sisfb_calc_pitch(ivideo, var);
-               sisfb_set_pitch(ivideo);
-
+               /* If acceleration to be used? Need to know
+                * before pre/post_set_mode()
+                */
                ivideo->accel = 0;
 #if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
 #ifdef STUPID_ACCELF_TEXT_SHIT
@@ -1175,6 +1341,17 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
                if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;
 #endif
 
+               if((ret = sisfb_set_mode(ivideo, 1))) {
+                       return ret;
+               }
+
+               ivideo->video_bpp    = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+               ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+               ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+
+               sisfb_calc_pitch(ivideo, var);
+               sisfb_set_pitch(ivideo);
+
                sisfb_set_vparms(ivideo);
 
                ivideo->current_width = ivideo->video_width;
@@ -1186,823 +1363,342 @@ sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *in
                ivideo->current_pixclock = var->pixclock;
                ivideo->current_refresh_rate = ivideo->refresh_rate;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
+               ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
 #endif
        }
 
        return 0;
 }
 
-static int
-sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+static void
+sisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base)
 {
-       unsigned int base;
-
-       if(var->xoffset > (var->xres_virtual - var->xres)) {
-               return -EINVAL;
-       }
-       if(var->yoffset > (var->yres_virtual - var->yres)) {
-               return -EINVAL;
-       }
-
-       base = (var->yoffset * var->xres_virtual) + var->xoffset;
-
-        /* calculate base bpp dep. */
-        switch(var->bits_per_pixel) {
-       case 32:
-               break;
-        case 16:
-               base >>= 1;
-               break;
-       case 8:
-        default:
-               base >>= 2;
-               break;
-        }
-       
        outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-        outSISIDXREG(SISCR, 0x0D, base & 0xFF);
+       outSISIDXREG(SISCR, 0x0D, base & 0xFF);
        outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
        outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
        if(ivideo->sisvga_engine == SIS_315_VGA) {
                setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
        }
-        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+}
+
+static void
+sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base)
+{
+       if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
                orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
-               outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
-               outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
-               outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
+               outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
+               outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
+               outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
                if(ivideo->sisvga_engine == SIS_315_VGA) {
                        setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
                }
-        }
-       return 0;
+       }
 }
 
-/* ------------ FBDev related routines for 2.4 series ----------- */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-
-static void
-sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+static int
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
-       u16 VRE, VBE, VRS, VBS, VDE, VT;
-       u16 HRE, HBE, HRS, HBS, HDE, HT;
-       u8  sr_data, cr_data, cr_data2, cr_data3, mr_data;
-       int A, B, C, D, E, F, temp;
-       unsigned int hrate, drate, maxyres;
-
-       inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);
+       if(var->xoffset > (var->xres_virtual - var->xres)) {
+               return -EINVAL;
+       }
+       if(var->yoffset > (var->yres_virtual - var->yres)) {
+               return -EINVAL;
+       }
 
-       if(sr_data & SIS_INTERLACED_MODE)
-          var->vmode = FB_VMODE_INTERLACED;
-       else
-          var->vmode = FB_VMODE_NONINTERLACED;
+       ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset;
 
-       switch((sr_data & 0x1C) >> 2) {
-       case SIS_8BPP_COLOR_MODE:
-               var->bits_per_pixel = 8;
+       /* calculate base bpp dep. */
+       switch(var->bits_per_pixel) {
+       case 32:
                break;
-       case SIS_16BPP_COLOR_MODE:
-               var->bits_per_pixel = 16;
+       case 16:
+               ivideo->current_base >>= 1;
                break;
-       case SIS_32BPP_COLOR_MODE:
-               var->bits_per_pixel = 32;
+       case 8:
+       default:
+               ivideo->current_base >>= 2;
                break;
        }
 
-       sisfb_bpp_to_var(ivideo, var);
-       
-       inSISIDXREG(SISSR, 0x0A, sr_data);
-        inSISIDXREG(SISCR, 0x06, cr_data);
-        inSISIDXREG(SISCR, 0x07, cr_data2);
-
-       VT = (cr_data & 0xFF) |
-            ((u16) (cr_data2 & 0x01) << 8) |
-            ((u16) (cr_data2 & 0x20) << 4) |
-            ((u16) (sr_data  & 0x01) << 10);
-       A = VT + 2;
-
-       inSISIDXREG(SISCR, 0x12, cr_data);
-
-       VDE = (cr_data & 0xff) |
-             ((u16) (cr_data2 & 0x02) << 7) |
-             ((u16) (cr_data2 & 0x40) << 3) |
-             ((u16) (sr_data  & 0x02) << 9);
-       E = VDE + 1;
-
-       inSISIDXREG(SISCR, 0x10, cr_data);
-
-       VRS = (cr_data & 0xff) |
-             ((u16) (cr_data2 & 0x04) << 6) |
-             ((u16) (cr_data2 & 0x80) << 2) |
-             ((u16) (sr_data  & 0x08) << 7);
-       F = VRS + 1 - E;
-
-       inSISIDXREG(SISCR, 0x15, cr_data);
-       inSISIDXREG(SISCR, 0x09, cr_data3);
-
-       if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
-
-       VBS = (cr_data & 0xff) |
-             ((u16) (cr_data2 & 0x08) << 5) |
-             ((u16) (cr_data3 & 0x20) << 4) |
-             ((u16) (sr_data & 0x04) << 8);
-
-       inSISIDXREG(SISCR, 0x16, cr_data);
-
-       VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);
-       temp = VBE - ((E - 1) & 511);
-       B = (temp > 0) ? temp : (temp + 512);
-
-       inSISIDXREG(SISCR, 0x11, cr_data);
-
-       VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);
-       temp = VRE - ((E + F - 1) & 31);
-       C = (temp > 0) ? temp : (temp + 32);
-
-       D = B - F - C;
-
-        var->yres = E;
-       var->upper_margin = D;
-       var->lower_margin = F;
-       var->vsync_len = C;
-
-       if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-          var->yres <<= 1;
-          var->upper_margin <<= 1;
-          var->lower_margin <<= 1;
-          var->vsync_len <<= 1;
-       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-          var->yres >>= 1;
-          var->upper_margin >>= 1;
-          var->lower_margin >>= 1;
-          var->vsync_len >>= 1;
-       }
-
-       inSISIDXREG(SISSR, 0x0b, sr_data);
-       inSISIDXREG(SISCR, 0x00, cr_data);
-
-       HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
-       A = HT + 5;
-
-       inSISIDXREG(SISCR, 0x01, cr_data);
-
-       HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);
-       E = HDE + 1;
-
-       inSISIDXREG(SISCR, 0x04, cr_data);
-
-       HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);
-       F = HRS - E - 3;
-
-       inSISIDXREG(SISCR, 0x02, cr_data);
+       ivideo->current_base += (ivideo->video_offset >> 2);
 
-       HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
+       sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+       sisfb_set_base_CRT2(ivideo, ivideo->current_base);
 
-       inSISIDXREG(SISSR, 0x0c, sr_data);
-       inSISIDXREG(SISCR, 0x03, cr_data);
-       inSISIDXREG(SISCR, 0x05, cr_data2);
-
-       HBE = (cr_data & 0x1f) |
-             ((u16) (cr_data2 & 0x80) >> 2) |
-             ((u16) (sr_data  & 0x03) << 6);
-       HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
-
-       temp = HBE - ((E - 1) & 255);
-       B = (temp > 0) ? temp : (temp + 256);
-
-       temp = HRE - ((E + F + 3) & 63);
-       C = (temp > 0) ? temp : (temp + 64);
-
-       D = B - F - C;
-
-       var->xres = E * 8;
-       if(var->xres_virtual < var->xres) {
-               var->xres_virtual = var->xres;
-       }
-
-       if((var->xres == 320) &&
-          (var->yres == 200 || var->yres == 240)) {
-               /* Terrible hack, but the correct CRTC data for
-                * these modes only produces a black screen...
-                */
-                       var->left_margin = (400 - 376);
-                       var->right_margin = (328 - 320);
-                       var->hsync_len = (376 - 328);
-       } else {
-               var->left_margin = D * 8;
-               var->right_margin = F * 8;
-               var->hsync_len = C * 8;
-       }
-       var->activate = FB_ACTIVATE_NOW;
+       return 0;
+}
 
-       var->sync = 0;
+/* ------------ FBDev related routines for 2.4 series ----------- */
 
-       mr_data = inSISREG(SISMISCR);
-       if(mr_data & 0x80)
-          var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
-       else
-          var->sync |= FB_SYNC_VERT_HIGH_ACT;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 
-       if(mr_data & 0x40)
-          var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
-       else
-          var->sync |= FB_SYNC_HOR_HIGH_ACT;
+#include "sisfb_fbdev_2_4.h"
 
-       VT += 2;
-       VT <<= 1;
-       HT = (HT + 5) * 8;
+#endif
 
-       if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-          VT <<= 1;
-       }
-       hrate = ivideo->refresh_rate * VT / 2;
-       drate = (hrate * HT) / 1000;
-       var->pixclock = (u32) (1000000000 / drate);
+/* ------------ FBDev related routines for 2.6 series ----------- */
 
-       if(ivideo->sisfb_ypan) {
-          maxyres = sisfb_calc_maxyres(ivideo, var);
-          if(ivideo->sisfb_max) {
-             var->yres_virtual = maxyres;
-          } else {
-             if(var->yres_virtual > maxyres) {
-                var->yres_virtual = maxyres;
-             }
-          }
-          if(var->yres_virtual <= var->yres) {
-             var->yres_virtual = var->yres;
-          }
-       } else {
-          var->yres_virtual = var->yres;
-       }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
+static int
+sisfb_open(struct fb_info *info, int user)
+{
+       return 0;
 }
 
 static int
-sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
-                        unsigned *transp, struct fb_info *info)
+sisfb_release(struct fb_info *info, int user)
 {
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-       if(regno >= ivideo->video_cmap_len) return 1;
-
-       *red   = ivideo->sis_palette[regno].red;
-       *green = ivideo->sis_palette[regno].green;
-       *blue  = ivideo->sis_palette[regno].blue;
-       *transp = 0;
-
        return 0;
 }
 
 static int
 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *info)
+               unsigned transp, struct fb_info *info)
 {
        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 
-       if(regno >= ivideo->video_cmap_len) return 1;
-
-       ivideo->sis_palette[regno].red   = red;
-       ivideo->sis_palette[regno].green = green;
-       ivideo->sis_palette[regno].blue  = blue;
+       if(regno >= sisfb_get_cmap_len(&info->var))
+               return 1;
 
-       switch(ivideo->video_bpp) {
-#ifdef FBCON_HAS_CFB8
+       switch(info->var.bits_per_pixel) {
        case 8:
-               outSISREG(SISDACA, regno);
+               outSISREG(SISDACA, regno);
                outSISREG(SISDACD, (red >> 10));
                outSISREG(SISDACD, (green >> 10));
                outSISREG(SISDACD, (blue >> 10));
                if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-                       outSISREG(SISDAC2A, regno);
+                       outSISREG(SISDAC2A, regno);
                        outSISREG(SISDAC2D, (red >> 8));
                        outSISREG(SISDAC2D, (green >> 8));
                        outSISREG(SISDAC2D, (blue >> 8));
                }
                break;
-#endif
-#ifdef FBCON_HAS_CFB16
        case 16:
-               ivideo->sis_fbcon_cmap.cfb16[regno] =
-                   ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
+               ((u32 *)(info->pseudo_palette))[regno] =
+                               (red & 0xf800)          |
+                               ((green & 0xfc00) >> 5) |
+                               ((blue & 0xf800) >> 11);
                break;
-#endif
-#ifdef FBCON_HAS_CFB32
        case 32:
-               red   >>= 8;
+               red >>= 8;
                green >>= 8;
-               blue  >>= 8;
-               ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
+               blue >>= 8;
+               ((u32 *)(info->pseudo_palette))[regno] =
+                               (red << 16) | (green << 8) | (blue);
                break;
-#endif
        }
-
        return 0;
 }
 
-static void
-sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
-{
-       struct sis_video_info    *ivideo = (struct sis_video_info *)info->par;
-       struct display           *display;
-       struct display_switch    *sw;
-       struct fb_fix_screeninfo fix;
-       long   flags;
-
-       display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
-       sisfb_get_fix(&fix, con, info);
-
-       display->var = *var;
-       display->screen_base = (char *)ivideo->video_vbase;
-       display->visual = fix.visual;
-       display->type = fix.type;
-       display->type_aux = fix.type_aux;
-       display->ypanstep = fix.ypanstep;
-       display->ywrapstep = fix.ywrapstep;
-       display->line_length = fix.line_length;
-       display->can_soft_blank = 1;
-       display->inverse = ivideo->sisfb_inverse;
-       display->next_line = fix.line_length;
-
-       save_flags(flags);
-
-       switch(ivideo->video_bpp) {
-#ifdef FBCON_HAS_CFB8
-       case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
-               break;
-#endif
-#ifdef FBCON_HAS_CFB16
-       case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
-               display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
-               break;
-#endif
-#ifdef FBCON_HAS_CFB32
-       case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
-               display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
-               break;
-#endif
-       default:sw = &fbcon_dummy;
-               break;
-       }
-       memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
-       display->dispsw = &ivideo->sisfb_sw;
-
-       restore_flags(flags);
-
-        if(ivideo->sisfb_ypan) {
-           /* display->scrollmode = 0;  */
-       } else {
-           display->scrollmode = SCROLL_YREDRAW;
-           ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
-       }
-}
-
-static void
-sisfb_do_install_cmap(int con, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-        if(con != ivideo->currcon) return;
-
-        if(fb_display[con].cmap.len) {
-               fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
-        } else {
-               int size = sisfb_get_cmap_len(&fb_display[con].var);
-               fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
-       }
-}
-
 static int
-sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+sisfb_set_par(struct fb_info *info)
 {
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-       if(con == -1) {
-               memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
-       } else {
-               *var = fb_display[con].var;
-       }
+       int err;
 
-       if(ivideo->sisfb_fstn) {
-               if(var->xres == 320 && var->yres == 480) var->yres = 240;
-        }
+       if((err = sisfb_do_set_var(&info->var, 1, info)))
+               return err;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
+       sisfb_get_fix(&info->fix, info->currcon, info);
+#else
+       sisfb_get_fix(&info->fix, -1, info);
+#endif
        return 0;
 }
 
 static int
-sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-       int err;
+       unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
+       unsigned int drate = 0, hrate = 0, maxyres;
+       int found_mode = 0;
+       int refresh_rate, search_idx, tidx;
+       BOOLEAN recalc_clock = FALSE;
+       u32 pixclock;
 
-       fb_display[con].var.activate = FB_ACTIVATE_NOW;
+       htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
 
-        if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
-               sisfb_crtc_to_var(ivideo, var);
-               return -EINVAL;
-       }
+       vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
 
-       sisfb_crtc_to_var(ivideo, var);
+       pixclock = var->pixclock;
 
-       sisfb_set_disp(con, var, info);
+       if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
+               vtotal += var->yres;
+               vtotal <<= 1;
+       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+               vtotal += var->yres;
+               vtotal <<= 2;
+       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+               vtotal += var->yres;
+               vtotal <<= 1;
+       } else
+               vtotal += var->yres;
 
-       if(info->changevar) {
-               (*info->changevar)(con);
+       if(!(htotal) || !(vtotal)) {
+               SISFAIL("sisfb: no valid timing data");
        }
 
-       if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
-               return err;
+       search_idx = 0;
+       while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
+              (sisbios_mode[search_idx].xres <= var->xres) ) {
+               if( (sisbios_mode[search_idx].xres == var->xres) &&
+                   (sisbios_mode[search_idx].yres == var->yres) &&
+                   (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
+                       if((tidx = sisfb_validate_mode(ivideo, search_idx,
+                                               ivideo->currentvbflags)) > 0) {
+                               found_mode = 1;
+                               search_idx = tidx;
+                               break;
+                       }
+               }
+               search_idx++;
        }
 
-       sisfb_do_install_cmap(con, info);
+       if(!found_mode) {
+               search_idx = 0;
+               while(sisbios_mode[search_idx].mode_no[0] != 0) {
+                  if( (var->xres <= sisbios_mode[search_idx].xres) &&
+                      (var->yres <= sisbios_mode[search_idx].yres) &&
+                      (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
+                       if((tidx = sisfb_validate_mode(ivideo,search_idx,
+                                               ivideo->currentvbflags)) > 0) {
+                               found_mode = 1;
+                               search_idx = tidx;
+                               break;
+                       }
+                  }
+                  search_idx++;
+               }
+               if(found_mode) {
+                       printk(KERN_DEBUG
+                               "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
+                               var->xres, var->yres, var->bits_per_pixel,
+                               sisbios_mode[search_idx].xres,
+                               sisbios_mode[search_idx].yres,
+                               var->bits_per_pixel);
+                       var->xres = sisbios_mode[search_idx].xres;
+                       var->yres = sisbios_mode[search_idx].yres;
+               } else {
+                       printk(KERN_ERR
+                               "sisfb: Failed to find supported mode near %dx%dx%d\n",
+                               var->xres, var->yres, var->bits_per_pixel);
+                       return -EINVAL;
+               }
+       }
 
-#if 0  /* Why was this called here? */
-       unsigned int cols, rows;
-       cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
-       rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
-       vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
-#endif
-       return 0;
-}
+       if( ((ivideo->vbflags2 & VB2_LVDS) ||
+            ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
+           (var->bits_per_pixel == 8) ) {
+               /* Slave modes on LVDS and 301B-DH */
+               refresh_rate = 60;
+               recalc_clock = TRUE;
+       } else if( (ivideo->current_htotal == htotal) &&
+                  (ivideo->current_vtotal == vtotal) &&
+                  (ivideo->current_pixclock == pixclock) ) {
+               /* x=x & y=y & c=c -> assume depth change */
+               drate = 1000000000 / pixclock;
+               hrate = (drate * 1000) / htotal;
+               refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+       } else if( ( (ivideo->current_htotal != htotal) ||
+                    (ivideo->current_vtotal != vtotal) ) &&
+                  (ivideo->current_pixclock == var->pixclock) ) {
+               /* x!=x | y!=y & c=c -> invalid pixclock */
+               if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
+                       refresh_rate =
+                               ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+               } else if(ivideo->sisfb_parm_rate != -1) {
+                       /* Sic, sisfb_parm_rate - want to know originally desired rate here */
+                       refresh_rate = ivideo->sisfb_parm_rate;
+               } else {
+                       refresh_rate = 60;
+               }
+               recalc_clock = TRUE;
+       } else if((pixclock) && (htotal) && (vtotal)) {
+               drate = 1000000000 / pixclock;
+               hrate = (drate * 1000) / htotal;
+               refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+       } else if(ivideo->current_refresh_rate) {
+               refresh_rate = ivideo->current_refresh_rate;
+               recalc_clock = TRUE;
+       } else {
+               refresh_rate = 60;
+               recalc_clock = TRUE;
+       }
 
-static int
-sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-       struct display *display;
+       myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
 
-       display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
+       /* Eventually recalculate timing and clock */
+       if(recalc_clock) {
+               if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
+               var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
+                                               sisbios_mode[search_idx].mode_no[ivideo->mni],
+                                               myrateindex));
+               sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,
+                                       sisbios_mode[search_idx].mode_no[ivideo->mni],
+                                       myrateindex, var);
+               if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+                       var->pixclock <<= 1;
+               }
+       }
 
-        if(con == ivideo->currcon) {
+       if(ivideo->sisfb_thismonitor.datavalid) {
+               if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
+                               myrateindex, refresh_rate)) {
+                       printk(KERN_INFO
+                               "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+               }
+       }
 
-               return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
+       /* Adapt RGB settings */
+       sisfb_bpp_to_var(ivideo, var);
 
-       } else if(display->cmap.len) {
-
-               fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
-
-       } else {
-
-               int size = sisfb_get_cmap_len(&display->var);
-               fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
-
-       }
-
-       return 0;
-}
-
-static int
-sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-       struct display *display;
-       int err, size;
-
-       display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
-
-       size = sisfb_get_cmap_len(&display->var);
-       if(display->cmap.len != size) {
-               err = fb_alloc_cmap(&display->cmap, size, 0);
-               if(err) return err;
-       }
-        
-       if(con == ivideo->currcon) {
-               return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
-       } else {
-               fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
-       }
-
-       return 0;
-}
-
-static int
-sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-       int err;
-
-       if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
-
-       if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
-          (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
-               return -EINVAL;
-       }
-
-        if(con == ivideo->currcon) {
-               if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
-       }
-
-       fb_display[con].var.xoffset = var->xoffset;
-       fb_display[con].var.yoffset = var->yoffset;
-
-       return 0;
-}
-
-static int
-sisfb_update_var(int con, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-        return(sisfb_pan_var(ivideo, &fb_display[con].var));
-}
-
-static int
-sisfb_switch(int con, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-       int cols, rows;
-
-        if(fb_display[ivideo->currcon].cmap.len) {
-               fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
-       }
-
-       fb_display[con].var.activate = FB_ACTIVATE_NOW;
-
-       if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
-                                       sizeof(struct fb_var_screeninfo))) {
-               ivideo->currcon = con;
-               return 1;
-       }
-
-       ivideo->currcon = con;
-
-       sisfb_do_set_var(&fb_display[con].var, 1, info);
-
-       sisfb_set_disp(con, &fb_display[con].var, info);
-
-       sisfb_do_install_cmap(con, info);
-
-       cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
-       rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
-       vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
-
-       sisfb_update_var(con, info);
-
-       return 1;
-}
-
-static void
-sisfb_blank(int blank, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-       sisfb_myblank(ivideo, blank);
-}
-#endif
-
-/* ------------ FBDev related routines for 2.6 series ----------- */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-
-static int
-sisfb_open(struct fb_info *info, int user)
-{
-       return 0;
-}
-
-static int
-sisfb_release(struct fb_info *info, int user)
-{
-       return 0;
-}
-
-static int
-sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-               unsigned transp, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-
-       if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
-
-       switch(info->var.bits_per_pixel) {
-       case 8:
-               outSISREG(SISDACA, regno);
-               outSISREG(SISDACD, (red >> 10));
-               outSISREG(SISDACD, (green >> 10));
-               outSISREG(SISDACD, (blue >> 10));
-               if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
-                       outSISREG(SISDAC2A, regno);
-                       outSISREG(SISDAC2D, (red >> 8));
-                       outSISREG(SISDAC2D, (green >> 8));
-                       outSISREG(SISDAC2D, (blue >> 8));
-               }
-               break;
-       case 16:
-               ((u32 *)(info->pseudo_palette))[regno] =
-                   ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
-               break;
-       case 32:
-               red >>= 8;
-               green >>= 8;
-               blue >>= 8;
-               ((u32 *)(info->pseudo_palette))[regno] =
-                               (red << 16) | (green << 8) | (blue);
-               break;
-       }
-       return 0;
-}
-
-static int
-sisfb_set_par(struct fb_info *info)
-{
-       int err;
-
-        if((err = sisfb_do_set_var(&info->var, 1, info))) {
-               return err;
-       }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
-       sisfb_get_fix(&info->fix, info->currcon, info);
-#else
-       sisfb_get_fix(&info->fix, -1, info);
-#endif
-       return 0;
-}
-
-static int
-sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-       struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
-       unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
-       unsigned int drate = 0, hrate = 0, maxyres;
-       int found_mode = 0;
-       int refresh_rate, search_idx;
-       BOOLEAN recalc_clock = FALSE;
-       u32 pixclock;
-
-       htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;
-
-       vtotal = var->upper_margin + var->lower_margin + var->vsync_len;
-
-       pixclock = var->pixclock;
-
-       if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {
-               vtotal += var->yres;
-               vtotal <<= 1;
-       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-               vtotal += var->yres;
-               vtotal <<= 2;
-       } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-               vtotal += var->yres;
-               vtotal <<= 1;
-       } else  vtotal += var->yres;
-
-       if(!(htotal) || !(vtotal)) {
-               SISFAIL("sisfb: no valid timing data");
-       }
-
-       search_idx = 0;
-       while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
-              (sisbios_mode[search_idx].xres <= var->xres) ) {
-               if( (sisbios_mode[search_idx].xres == var->xres) &&
-                   (sisbios_mode[search_idx].yres == var->yres) &&
-                   (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
-                       if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
-                          found_mode = 1;
-                          break;
-                       }
-               }
-               search_idx++;
-       }
-
-       if(!found_mode) {
-                search_idx = 0;
-               while(sisbios_mode[search_idx].mode_no[0] != 0) {
-                  if( (var->xres <= sisbios_mode[search_idx].xres) &&
-                      (var->yres <= sisbios_mode[search_idx].yres) &&
-                      (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
-                         if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
-                            found_mode = 1;
-                            break;
-                         }
-                  }
-                  search_idx++;
-               }
-               if(found_mode) {
-                       printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",
-                               var->xres, var->yres, var->bits_per_pixel,
-                               sisbios_mode[search_idx].xres,
-                               sisbios_mode[search_idx].yres,
-                               var->bits_per_pixel);
-                       var->xres = sisbios_mode[search_idx].xres;
-                       var->yres = sisbios_mode[search_idx].yres;
+       /* Sanity check for offsets */
+       if(var->xoffset < 0) var->xoffset = 0;
+       if(var->yoffset < 0) var->yoffset = 0;
 
+       if(var->xres > var->xres_virtual)
+               var->xres_virtual = var->xres;
 
+       if(ivideo->sisfb_ypan) {
+               maxyres = sisfb_calc_maxyres(ivideo, var);
+               if(ivideo->sisfb_max) {
+                       var->yres_virtual = maxyres;
                } else {
-                       printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n",
-                               var->xres, var->yres, var->bits_per_pixel);
-                       return -EINVAL;
+                       if(var->yres_virtual > maxyres) {
+                               var->yres_virtual = maxyres;
+                       }
                }
-       }
-
-       if( ((ivideo->vbflags & VB_LVDS) ||                     /* Slave modes on LVDS and 301B-DH */
-            ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
-           (var->bits_per_pixel == 8) ) {
-               refresh_rate = 60;
-               recalc_clock = TRUE;
-       } else if( (ivideo->current_htotal == htotal) &&        /* x=x & y=y & c=c -> assume depth change */
-                  (ivideo->current_vtotal == vtotal) &&
-                  (ivideo->current_pixclock == pixclock) ) {
-               drate = 1000000000 / pixclock;
-               hrate = (drate * 1000) / htotal;
-               refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-       } else if( ( (ivideo->current_htotal != htotal) ||      /* x!=x | y!=y & c=c -> invalid pixclock */
-                    (ivideo->current_vtotal != vtotal) ) &&
-                  (ivideo->current_pixclock == var->pixclock) ) {
-               if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
-                       refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
-               } else if(ivideo->sisfb_parm_rate != -1) {
-                       /* Sic, sisfb_parm_rate - want to know originally desired rate here */
-                       refresh_rate = ivideo->sisfb_parm_rate;
-               } else {
-                       refresh_rate = 60;
+               if(var->yres_virtual <= var->yres) {
+                       var->yres_virtual = var->yres;
                }
-               recalc_clock = TRUE;
-       } else if((pixclock) && (htotal) && (vtotal)) {
-               drate = 1000000000 / pixclock;
-               hrate = (drate * 1000) / htotal;
-               refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-       } else if(ivideo->current_refresh_rate) {
-               refresh_rate = ivideo->current_refresh_rate;
-               recalc_clock = TRUE;
        } else {
-               refresh_rate = 60;
-               recalc_clock = TRUE;
-       }
-
-       myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
-
-       /* Eventually recalculate timing and clock */
-       if(recalc_clock) {
-          if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
-          var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,
-                                               &ivideo->sishw_ext,
-                                               sisbios_mode[search_idx].mode_no[ivideo->mni],
-                                               myrateindex));
-          sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
-                                   sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex, var);
-          if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-             var->pixclock <<= 1;
-          }
-       }
-
-       if(ivideo->sisfb_thismonitor.datavalid) {
-          if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
-                                myrateindex, refresh_rate)) {
-             printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
-          }
-       }
-
-       /* Adapt RGB settings */
-       sisfb_bpp_to_var(ivideo, var);
-       
-       /* Sanity check for offsets */
-       if(var->xoffset < 0) var->xoffset = 0;
-       if(var->yoffset < 0) var->yoffset = 0;
-
-       if(var->xres > var->xres_virtual) {
-          var->xres_virtual = var->xres;
+               if(var->yres != var->yres_virtual) {
+                       var->yres_virtual = var->yres;
+               }
+               var->xoffset = 0;
+               var->yoffset = 0;
        }
 
-       if(ivideo->sisfb_ypan) {
-          maxyres = sisfb_calc_maxyres(ivideo, var);
-          if(ivideo->sisfb_max) {
-             var->yres_virtual = maxyres;
-          } else {
-             if(var->yres_virtual > maxyres) {
-                var->yres_virtual = maxyres;
-             }
-          }
-          if(var->yres_virtual <= var->yres) {
-             var->yres_virtual = var->yres;
-          }
-       } else {
-          if(var->yres != var->yres_virtual) {
-             var->yres_virtual = var->yres;
-          }
-          var->xoffset = 0;
-          var->yoffset = 0;
-       }
-       
        /* Truncate offsets to maximum if too high */
        if(var->xoffset > var->xres_virtual - var->xres) {
-          var->xoffset = var->xres_virtual - var->xres - 1;
+               var->xoffset = var->xres_virtual - var->xres - 1;
        }
 
        if(var->yoffset > var->yres_virtual - var->yres) {
-          var->yoffset = var->yres_virtual - var->yres - 1;
+               var->yoffset = var->yres_virtual - var->yres - 1;
        }
-       
+
        /* Set everything else to 0 */
-       var->red.msb_right = 
-       var->green.msb_right =
-       var->blue.msb_right =
-       var->transp.offset =
-       var->transp.length =
-       var->transp.msb_right = 0;
+       var->red.msb_right =
+               var->green.msb_right =
+               var->blue.msb_right =
+               var->transp.offset =
+               var->transp.length =
+               var->transp.msb_right = 0;
 
        return 0;
 }
@@ -2013,21 +1709,21 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
        int err;
 
-       if(var->xoffset > (var->xres_virtual - var->xres)) {
+       if(var->xoffset > (var->xres_virtual - var->xres))
                return -EINVAL;
-       }
-       if(var->yoffset > (var->yres_virtual - var->yres)) {
+
+       if(var->yoffset > (var->yres_virtual - var->yres))
                return -EINVAL;
-       }
 
-       if(var->vmode & FB_VMODE_YWRAP) return -EINVAL;
+       if(var->vmode & FB_VMODE_YWRAP)
+               return -EINVAL;
 
        if(var->xoffset + info->var.xres > info->var.xres_virtual ||
-          var->yoffset + info->var.yres > info->var.yres_virtual) {
+          var->yoffset + info->var.yres > info->var.yres_virtual)
                return -EINVAL;
-       }
 
-       if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
+       if((err = sisfb_pan_var(ivideo, var)) < 0)
+               return err;
 
        info->var.xoffset = var->xoffset;
        info->var.yoffset = var->yoffset;
@@ -2040,7 +1736,7 @@ sisfb_blank(int blank, struct fb_info *info)
 {
        struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 
-       return(sisfb_myblank(ivideo, blank));
+       return sisfb_myblank(ivideo, blank);
 }
 
 #endif
@@ -2056,153 +1752,184 @@ sisfb_ioctl(struct inode *inode, struct file *file,
            struct fb_info *info)
 {
        struct sis_video_info   *ivideo = (struct sis_video_info *)info->par;
-       struct sis_memreq       sismemreq;
-       struct fb_vblank        sisvbblank;
-       sisfb_info              x;
+       struct sis_memreq       sismemreq;
+       struct fb_vblank        sisvbblank;
        u32                     gpu32 = 0;
 #ifndef __user
 #define __user
 #endif
        u32 __user              *argp = (u32 __user *)arg;
 
-       switch (cmd) {
+       switch(cmd) {
           case FBIO_ALLOC:
-               if(!capable(CAP_SYS_RAWIO)) {
+               if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
-               }
-               if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq))) {
-                       return -EFAULT;
-               }
+
+               if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))
+                       return -EFAULT;
+
                sis_malloc(&sismemreq);
+
                if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {
                        sis_free((u32)sismemreq.offset);
-                       return -EFAULT;
+                       return -EFAULT;
                }
                break;
 
           case FBIO_FREE:
-               if(!capable(CAP_SYS_RAWIO)) {
+               if(!capable(CAP_SYS_RAWIO))
                        return -EPERM;
-               }
-               if(get_user(gpu32, argp)) {
+
+               if(get_user(gpu32, argp))
                        return -EFAULT;
-               }
+
                sis_free(gpu32);
                break;
 
           case FBIOGET_VBLANK:
                sisvbblank.count = 0;
                sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
-               if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank))) {
+
+               if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))
                        return -EFAULT;
-               }
+
                break;
 
           case SISFB_GET_INFO_SIZE:
-               return put_user(sizeof(sisfb_info), argp);
+               return put_user(sizeof(struct sisfb_info), argp);
 
           case SISFB_GET_INFO_OLD:
-               if(ivideo->warncount++ < 50) {
-                  printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
-               }
+               if(ivideo->warncount++ < 10)
+                       printk(KERN_INFO
+                               "sisfb: Deprecated ioctl call received - update your application!\n");
           case SISFB_GET_INFO:  /* For communication with X driver */
-               x.sisfb_id         = SISFB_ID;
-               x.sisfb_version    = VER_MAJOR;
-               x.sisfb_revision   = VER_MINOR;
-               x.sisfb_patchlevel = VER_LEVEL;
-               x.chip_id = ivideo->chip_id;
-               x.memory = ivideo->video_size / 1024;
-               x.heapstart = ivideo->heapstart / 1024;
+               ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;
+               ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;
+               ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;
+               ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;
+               ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;
+               ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;
+               ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;
+               ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;
                if(ivideo->modechanged) {
-                  x.fbvidmode = ivideo->mode_no;
+                       ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;
                } else {
-                  x.fbvidmode = ivideo->modeprechange;
-               }
-               x.sisfb_caps = ivideo->caps;
-               x.sisfb_tqlen = 512; /* yet fixed */
-               x.sisfb_pcibus = ivideo->pcibus;
-               x.sisfb_pcislot = ivideo->pcislot;
-               x.sisfb_pcifunc = ivideo->pcifunc;
-               x.sisfb_lcdpdc = ivideo->detectedpdc;
-               x.sisfb_lcdpdca = ivideo->detectedpdca;
-               x.sisfb_lcda = ivideo->detectedlcda;
-               x.sisfb_vbflags = ivideo->vbflags;
-               x.sisfb_currentvbflags = ivideo->currentvbflags;
-               x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
-               x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
-               x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
-               x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
-               x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
-               x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
-               x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
-               x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
-               x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
-               x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
-
-               if(copy_to_user((void __user *)arg, &x, sizeof(x))) {
-                       return -EFAULT;
+                       ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;
                }
+               ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;
+               ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;
+               ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;
+               ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;
+               ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;
+               ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;
+               ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;
+               ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;
+               ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;
+               ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;
+               ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+               ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+               ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+               ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+               ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+               ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+               ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+               ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+               ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+               ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+               ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;
+               ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;
+               ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;
+               ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;
+               ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;
+               ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;
+               ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;
+               ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;
+
+               if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,
+                                               sizeof(ivideo->sisfb_infoblock)))
+                       return -EFAULT;
+
                break;
 
           case SISFB_GET_VBRSTATUS_OLD:
-               if(ivideo->warncount++ < 50) {
-                  printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
-               }
+               if(ivideo->warncount++ < 10)
+                       printk(KERN_INFO
+                               "sisfb: Deprecated ioctl call received - update your application!\n");
           case SISFB_GET_VBRSTATUS:
-               if(sisfb_CheckVBRetrace(ivideo)) {
+               if(sisfb_CheckVBRetrace(ivideo))
                        return put_user((u32)1, argp);
-               } else {
+               else
                        return put_user((u32)0, argp);
-               }
 
           case SISFB_GET_AUTOMAXIMIZE_OLD:
-               if(ivideo->warncount++ < 50) {
-                  printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
-               }
+               if(ivideo->warncount++ < 10)
+                       printk(KERN_INFO
+                               "sisfb: Deprecated ioctl call received - update your application!\n");
           case SISFB_GET_AUTOMAXIMIZE:
-               if(ivideo->sisfb_max)   return put_user((u32)1, argp);
-               else                    return put_user((u32)0, argp);
+               if(ivideo->sisfb_max)
+                       return put_user((u32)1, argp);
+               else
+                       return put_user((u32)0, argp);
 
           case SISFB_SET_AUTOMAXIMIZE_OLD:
-               if(ivideo->warncount++ < 50) {
-                  printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
-               }
+               if(ivideo->warncount++ < 10)
+                       printk(KERN_INFO
+                               "sisfb: Deprecated ioctl call received - update your application!\n");
           case SISFB_SET_AUTOMAXIMIZE:
-               if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+               if(get_user(gpu32, argp))
                        return -EFAULT;
-               }
+
                ivideo->sisfb_max = (gpu32) ? 1 : 0;
                break;
 
           case SISFB_SET_TVPOSOFFSET:
-               if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+               if(get_user(gpu32, argp))
                        return -EFAULT;
-               }
+
                sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
                sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
                break;
 
           case SISFB_GET_TVPOSOFFSET:
-               return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
-                               argp);
+               return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),
+                                                       argp);
+
+          case SISFB_COMMAND:
+               if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,
+                                                       sizeof(struct sisfb_cmd)))
+                       return -EFAULT;
+
+               sisfb_handle_command(ivideo, &ivideo->sisfb_command);
+
+               if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,
+                                                       sizeof(struct sisfb_cmd)))
+                       return -EFAULT;
+
+               break;
 
           case SISFB_SET_LOCK:
-               if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {
+               if(get_user(gpu32, argp))
                        return -EFAULT;
-               }
+
                ivideo->sisfblocked = (gpu32) ? 1 : 0;
                break;
 
           default:
+#ifdef SIS_NEW_CONFIG_COMPAT
                return -ENOIOCTLCMD;
+#else
+               return -EINVAL;
+#endif
        }
        return 0;
 }
 
-#ifdef CONFIG_COMPAT
-static long sisfb_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg, struct fb_info *info)
+#ifdef SIS_NEW_CONFIG_COMPAT
+static long
+sisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info)
 {
        int ret;
+
        lock_kernel();
        ret = sisfb_ioctl(NULL, f, cmd, arg, info);
        unlock_kernel();
@@ -2219,7 +1946,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 
        strcpy(fix->id, ivideo->myid);
 
-       fix->smem_start  = ivideo->video_base;
+       fix->smem_start  = ivideo->video_base + ivideo->video_offset;
        fix->smem_len    = ivideo->sisfb_mem;
        fix->type        = FB_TYPE_PACKED_PIXELS;
        fix->type_aux    = 0;
@@ -2231,11 +1958,17 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
        fix->mmio_start  = ivideo->mmio_base;
        fix->mmio_len    = ivideo->mmio_size;
        if(ivideo->sisvga_engine == SIS_300_VGA) {
-          fix->accel    = FB_ACCEL_SIS_GLAMOUR;
-       } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {
-          fix->accel    = FB_ACCEL_SIS_XABRE;
+               fix->accel = FB_ACCEL_SIS_GLAMOUR;
+       } else if((ivideo->chip == SIS_330) ||
+                 (ivideo->chip == SIS_760) ||
+                 (ivideo->chip == SIS_761)) {
+               fix->accel = FB_ACCEL_SIS_XABRE;
+       } else if(ivideo->chip == XGI_20) {
+               fix->accel = FB_ACCEL_XGI_VOLARI_Z;
+       } else if(ivideo->chip >= XGI_40) {
+               fix->accel = FB_ACCEL_XGI_VOLARI_V;
        } else {
-          fix->accel    = FB_ACCEL_SIS_GLAMOUR_2;
+               fix->accel = FB_ACCEL_SIS_GLAMOUR_2;
        }
 
        return 0;
@@ -2251,40 +1984,41 @@ static struct fb_ops sisfb_ops = {
        .fb_set_var     = sisfb_set_var,
        .fb_get_cmap    = sisfb_get_cmap,
        .fb_set_cmap    = sisfb_set_cmap,
-        .fb_pan_display = sisfb_pan_display,
+       .fb_pan_display = sisfb_pan_display,
        .fb_ioctl       = sisfb_ioctl
 };
 #endif
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static struct fb_ops sisfb_ops = {
-       .owner          = THIS_MODULE,
-       .fb_open        = sisfb_open,
-       .fb_release     = sisfb_release,
-       .fb_check_var   = sisfb_check_var,
-       .fb_set_par     = sisfb_set_par,
-       .fb_setcolreg   = sisfb_setcolreg,
-        .fb_pan_display = sisfb_pan_display,
-        .fb_blank       = sisfb_blank,
-       .fb_fillrect    = fbcon_sis_fillrect,
-       .fb_copyarea    = fbcon_sis_copyarea,
-       .fb_imageblit   = cfb_imageblit,
-       .fb_cursor      = soft_cursor,
-       .fb_sync        = fbcon_sis_sync,
-       .fb_ioctl       = sisfb_ioctl,
-#ifdef CONFIG_COMPAT
-       .fb_compat_ioctl = sisfb_compat_ioctl,
+       .owner          = THIS_MODULE,
+       .fb_open        = sisfb_open,
+       .fb_release     = sisfb_release,
+       .fb_check_var   = sisfb_check_var,
+       .fb_set_par     = sisfb_set_par,
+       .fb_setcolreg   = sisfb_setcolreg,
+       .fb_pan_display = sisfb_pan_display,
+       .fb_blank       = sisfb_blank,
+       .fb_fillrect    = fbcon_sis_fillrect,
+       .fb_copyarea    = fbcon_sis_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_cursor      = soft_cursor,
+       .fb_sync        = fbcon_sis_sync,
+#ifdef SIS_NEW_CONFIG_COMPAT
+       .fb_compat_ioctl= sisfb_compat_ioctl,
 #endif
+       .fb_ioctl       = sisfb_ioctl
 };
 #endif
 
 /* ---------------- Chip generation dependent routines ---------------- */
 
-static struct pci_dev * sisfb_get_northbridge(int basechipid)
+static struct pci_dev * __devinit
+sisfb_get_northbridge(int basechipid)
 {
        struct pci_dev *pdev = NULL;
        int nbridgenum, nbridgeidx, i;
-       const unsigned short nbridgeids[] = {
+       static const unsigned short nbridgeids[] = {
                PCI_DEVICE_ID_SI_540,   /* for SiS 540 VGA */
                PCI_DEVICE_ID_SI_630,   /* for SiS 630/730 VGA */
                PCI_DEVICE_ID_SI_730,
@@ -2292,13 +2026,14 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
                PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
                PCI_DEVICE_ID_SI_651,
                PCI_DEVICE_ID_SI_740,
-               PCI_DEVICE_ID_SI_661,   /* for SiS 661/741/660/760 VGA */
+               PCI_DEVICE_ID_SI_661,   /* for SiS 661/741/660/760/761 VGA */
                PCI_DEVICE_ID_SI_741,
                PCI_DEVICE_ID_SI_660,
-               PCI_DEVICE_ID_SI_760
+               PCI_DEVICE_ID_SI_760,
+               PCI_DEVICE_ID_SI_761
        };
 
-       switch(basechipid) {
+       switch(basechipid) {
 #ifdef CONFIG_FB_SIS_300
        case SIS_540:   nbridgeidx = 0; nbridgenum = 1; break;
        case SIS_630:   nbridgeidx = 1; nbridgenum = 2; break;
@@ -2306,35 +2041,40 @@ static struct pci_dev * sisfb_get_northbridge(int basechipid)
 #ifdef CONFIG_FB_SIS_315
        case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
        case SIS_650:   nbridgeidx = 4; nbridgenum = 3; break;
-       case SIS_660:   nbridgeidx = 7; nbridgenum = 4; break;
+       case SIS_660:   nbridgeidx = 7; nbridgenum = 5; break;
 #endif
        default:        return NULL;
        }
        for(i = 0; i < nbridgenum; i++) {
-               if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
+               if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI,
+                               nbridgeids[nbridgeidx+i], NULL)))
+                       break;
        }
        return pdev;
 }
 
-static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
+static int __devinit
+sisfb_get_dram_size(struct sis_video_info *ivideo)
 {
 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
        u8 reg;
 #endif
 
        ivideo->video_size = 0;
+       ivideo->UMAsize = ivideo->LFBsize = 0;
 
        switch(ivideo->chip) {
 #ifdef CONFIG_FB_SIS_300
        case SIS_300:
-               inSISIDXREG(SISSR, 0x14, reg);
+               inSISIDXREG(SISSR, 0x14, reg);
                ivideo->video_size = ((reg & 0x3F) + 1) << 20;
                break;
        case SIS_540:
        case SIS_630:
        case SIS_730:
-               if(!ivideo->nbridge) return -1;
-               pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+               if(!ivideo->nbridge)
+                       return -1;
+               pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
                ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
                break;
 #endif
@@ -2342,45 +2082,68 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
        case SIS_315H:
        case SIS_315PRO:
        case SIS_315:
-               inSISIDXREG(SISSR, 0x14, reg);
+               inSISIDXREG(SISSR, 0x14, reg);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
                switch((reg >> 2) & 0x03) {
                case 0x01:
                case 0x03:
-                  ivideo->video_size <<= 1;
-                  break;
+                       ivideo->video_size <<= 1;
+                       break;
                case 0x02:
-                  ivideo->video_size += (ivideo->video_size/2);
+                       ivideo->video_size += (ivideo->video_size/2);
                }
-               break;
+               break;
        case SIS_330:
-               inSISIDXREG(SISSR, 0x14, reg);
+               inSISIDXREG(SISSR, 0x14, reg);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
                if(reg & 0x0c) ivideo->video_size <<= 1;
-               break;
+               break;
        case SIS_550:
        case SIS_650:
        case SIS_740:
-               inSISIDXREG(SISSR, 0x14, reg);
+               inSISIDXREG(SISSR, 0x14, reg);
                ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
                break;
        case SIS_661:
        case SIS_741:
-               inSISIDXREG(SISCR, 0x79, reg);
+               inSISIDXREG(SISCR, 0x79, reg);
                ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-               break;
+               break;
        case SIS_660:
        case SIS_760:
+       case SIS_761:
                inSISIDXREG(SISCR, 0x79, reg);
                reg = (reg & 0xf0) >> 4;
-               if(reg) ivideo->video_size = (1 << reg) << 20;
+               if(reg) {
+                       ivideo->video_size = (1 << reg) << 20;
+                       ivideo->UMAsize = ivideo->video_size;
+               }
                inSISIDXREG(SISCR, 0x78, reg);
                reg &= 0x30;
                if(reg) {
-                  if(reg == 0x10) ivideo->video_size += (32 << 20);
-                  else            ivideo->video_size += (64 << 20);
+                       if(reg == 0x10) {
+                               ivideo->LFBsize = (32 << 20);
+                       } else {
+                               ivideo->LFBsize = (64 << 20);
+                       }
+                       ivideo->video_size += ivideo->LFBsize;
+               }
+               break;
+       case SIS_340:
+       case XGI_20:
+       case XGI_40:
+               inSISIDXREG(SISSR, 0x14, reg);
+               ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+               if(ivideo->chip != XGI_20) {
+                       reg = (reg & 0x0c) >> 2;
+                       if(ivideo->revision_id == 2) {
+                               if(reg & 0x01) reg = 0x02;
+                               else           reg = 0x00;
+                       }
+                       if(reg == 0x02)         ivideo->video_size <<= 1;
+                       else if(reg == 0x03)    ivideo->video_size <<= 2;
                }
-               break;
+               break;
 #endif
        default:
                return -1;
@@ -2390,17 +2153,24 @@ static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
 
 /* -------------- video bridge device detection --------------- */
 
-static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 {
        u8 cr32, temp;
 
+       /* No CRT2 on XGI Z7 */
+       if(ivideo->chip == XGI_20) {
+               ivideo->sisfb_crt1off = 0;
+               return;
+       }
+
 #ifdef CONFIG_FB_SIS_300
        if(ivideo->sisvga_engine == SIS_300_VGA) {
                inSISIDXREG(SISSR, 0x17, temp);
                if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
                        /* PAL/NTSC is stored on SR16 on such machines */
                        if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-                               inSISIDXREG(SISSR, 0x16, temp);
+                               inSISIDXREG(SISSR, 0x16, temp);
                                if(temp & 0x20)
                                        ivideo->vbflags |= TV_PAL;
                                else
@@ -2435,28 +2205,29 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 
        if(ivideo->sisfb_tvplug != -1) {
           if( (ivideo->sisvga_engine != SIS_315_VGA) ||
-              (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
+              (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) {
              if(ivideo->sisfb_tvplug & TV_YPBPR) {
-                ivideo->sisfb_tvplug = -1;
+                ivideo->sisfb_tvplug = -1;
                 printk(KERN_ERR "sisfb: YPbPr not supported\n");
              }
           }
        }
        if(ivideo->sisfb_tvplug != -1) {
           if( (ivideo->sisvga_engine != SIS_315_VGA) ||
-              (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
+              (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) {
              if(ivideo->sisfb_tvplug & TV_HIVISION) {
-                ivideo->sisfb_tvplug = -1;
+                ivideo->sisfb_tvplug = -1;
                 printk(KERN_ERR "sisfb: HiVision not supported\n");
              }
           }
        }
        if(ivideo->sisfb_tvstd != -1) {
-          if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
-              (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
+          if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
+              (!((ivideo->sisvga_engine == SIS_315_VGA) &&
+                       (ivideo->vbflags2 & VB2_CHRONTEL))) ) {
              if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
-                ivideo->sisfb_tvstd = -1;
-                printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+                ivideo->sisfb_tvstd = -1;
+                printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
              }
           }
        }
@@ -2468,7 +2239,7 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
                if(cr32 & SIS_VB_YPBPR)          ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
                else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
                else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
-               else {
+               else {
                        if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
                        if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
                }
@@ -2485,165 +2256,44 @@ static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
            }
            if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
                if(ivideo->sisvga_engine == SIS_300_VGA) {
-                       inSISIDXREG(SISSR, 0x38, temp);
+                       inSISIDXREG(SISSR, 0x38, temp);
                        if(temp & 0x01) ivideo->vbflags |= TV_PAL;
                        else            ivideo->vbflags |= TV_NTSC;
                } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
-                       inSISIDXREG(SISSR, 0x38, temp);
+                       inSISIDXREG(SISSR, 0x38, temp);
                        if(temp & 0x01) ivideo->vbflags |= TV_PAL;
                        else            ivideo->vbflags |= TV_NTSC;
-               } else {
-                       inSISIDXREG(SISCR, 0x79, temp);
+               } else {
+                       inSISIDXREG(SISCR, 0x79, temp);
                        if(temp & 0x20) ivideo->vbflags |= TV_PAL;
                        else            ivideo->vbflags |= TV_NTSC;
-               }
+               }
            }
        }
 
        /* Copy forceCRT1 option to CRT1off if option is given */
-       if(ivideo->sisfb_forcecrt1 != -1) {
-          ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
-       }
-}
-
-static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
-{
-       char stdstr[]    = "sisfb: Detected";
-       char bridgestr[] = "video bridge";
-       u8 vb_chipid;
-       u8 reg;
-
-       inSISIDXREG(SISPART4, 0x00, vb_chipid);
-       switch(vb_chipid) {
-       case 0x01:
-               inSISIDXREG(SISPART4, 0x01, reg);
-               if(reg < 0xb0) {
-                       ivideo->vbflags |= VB_301;
-                       printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
-               } else if(reg < 0xc0) {
-                       ivideo->vbflags |= VB_301B;
-                       inSISIDXREG(SISPART4,0x23,reg);
-                       if(!(reg & 0x02)) {
-                          ivideo->vbflags |= VB_30xBDH;
-                          printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
-                       } else {
-                          printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
-                       }
-               } else if(reg < 0xd0) {
-                       ivideo->vbflags |= VB_301C;
-                       printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
-               } else if(reg < 0xe0) {
-                       ivideo->vbflags |= VB_301LV;
-                       printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
-               } else if(reg <= 0xe1) {
-                       inSISIDXREG(SISPART4,0x39,reg);
-                       if(reg == 0xff) {
-                          ivideo->vbflags |= VB_302LV;
-                          printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
-                       } else {
-                          ivideo->vbflags |= VB_301C;
-                          printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
-#if 0
-                          ivideo->vbflags |= VB_302ELV;
-                          printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
-#endif
-                       }
-               }
-               break;
-       case 0x02:
-               ivideo->vbflags |= VB_302B;
-               printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
-               break;
-       }
-
-       if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
-               inSISIDXREG(SISCR, 0x37, reg);
-               reg &= SIS_EXTERNAL_CHIP_MASK;
-               reg >>= 1;
-               if(ivideo->sisvga_engine == SIS_300_VGA) {
-#ifdef CONFIG_FB_SIS_300
-                       switch(reg) {
-                          case SIS_EXTERNAL_CHIP_LVDS:
-                               ivideo->vbflags |= VB_LVDS;
-                               break;
-                          case SIS_EXTERNAL_CHIP_TRUMPION:
-                               ivideo->vbflags |= VB_TRUMPION;
-                               break;
-                          case SIS_EXTERNAL_CHIP_CHRONTEL:
-                               ivideo->vbflags |= VB_CHRONTEL;
-                               break;
-                          case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
-                               ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
-                               break;
-                       }
-                       if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
-#endif
-               } else if(ivideo->chip < SIS_661) {
-#ifdef CONFIG_FB_SIS_315
-                       switch (reg) {
-                          case SIS310_EXTERNAL_CHIP_LVDS:
-                               ivideo->vbflags |= VB_LVDS;
-                               break;
-                          case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
-                               ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
-                               break;
-                       }
-                       if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
-#endif
-               } else if(ivideo->chip >= SIS_661) {
-#ifdef CONFIG_FB_SIS_315
-                       inSISIDXREG(SISCR, 0x38, reg);
-                       reg >>= 5;
-                       switch(reg) {
-                          case 0x02:
-                               ivideo->vbflags |= VB_LVDS;
-                               break;
-                          case 0x03:
-                               ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
-                               break;
-                          case 0x04:
-                               ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
-                               break;
-                       }
-                       if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
-#endif
-               }
-               if(ivideo->vbflags & VB_LVDS) {
-                  printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
-               }
-               if(ivideo->vbflags & VB_TRUMPION) {
-                  printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
-               }
-               if(ivideo->vbflags & VB_CHRONTEL) {
-                  printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
-               }
-               if(ivideo->vbflags & VB_CONEXANT) {
-                  printk(KERN_INFO "%s Conexant external device\n", stdstr);
-               }
-       }
-
-       if(ivideo->vbflags & VB_SISBRIDGE) {
-               SiS_Sense30x(ivideo);
-       } else if(ivideo->vbflags & VB_CHRONTEL) {
-               SiS_SenseCh(ivideo);
+       if(ivideo->sisfb_forcecrt1 != -1) {
+          ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
        }
 }
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
+static BOOLEAN __devinit
+sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
     int count = 48;
 
     old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
     do {
-               if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
+       if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
     } while(count--);
     return (count == -1) ? FALSE : TRUE;
 }
 
-static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
     BOOLEAN mustwait = FALSE;
     u8  sr1F, cr17;
@@ -2699,7 +2349,8 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
     if(temp == 0xffff) {
        i = 3;
        do {
-          temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
+         temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+               ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
        } while(((temp == 0) || (temp == 0xffff)) && i--);
 
        if((temp == 0) || (temp == 0xffff)) {
@@ -2723,7 +2374,96 @@ static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
 }
 
 /* Determine and detect attached devices on SiS30x */
-static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
+static void __devinit
+SiS_SenseLCD(struct sis_video_info *ivideo)
+{
+       unsigned char buffer[256];
+       unsigned short temp, realcrtno, i;
+       u8 reg, cr37 = 0, paneltype = 0;
+       u16 xres, yres;
+
+       ivideo->SiS_Pr.PanelSelfDetected = FALSE;
+
+       /* LCD detection only for TMDS bridges */
+       if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
+               return;
+       if(ivideo->vbflags2 & VB2_30xBDH)
+               return;
+
+       /* If LCD already set up by BIOS, skip it */
+       inSISIDXREG(SISCR, 0x32, reg);
+       if(reg & 0x08)
+               return;
+
+       realcrtno = 1;
+       if(ivideo->SiS_Pr.DDCPortMixup)
+               realcrtno = 0;
+
+       /* Check DDC capabilities */
+       temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
+                               realcrtno, 0, &buffer[0], ivideo->vbflags2);
+
+       if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
+               return;
+
+       /* Read DDC data */
+       i = 3;  /* Number of retrys */
+       do {
+               temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+                               ivideo->sisvga_engine, realcrtno, 1,
+                               &buffer[0], ivideo->vbflags2);
+       } while((temp) && i--);
+
+       if(temp)
+               return;
+
+       /* No digital device */
+       if(!(buffer[0x14] & 0x80))
+               return;
+
+       /* First detailed timing preferred timing? */
+       if(!(buffer[0x18] & 0x02))
+               return;
+
+       xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
+       yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4);
+
+       switch(xres) {
+               case 1024:
+                       if(yres == 768)
+                               paneltype = 0x02;
+                       break;
+               case 1280:
+                       if(yres == 1024)
+                               paneltype = 0x03;
+                       break;
+               case 1600:
+                       if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
+                               paneltype = 0x0b;
+                       break;
+       }
+
+       if(!paneltype)
+               return;
+
+       if(buffer[0x23])
+               cr37 |= 0x10;
+
+       if((buffer[0x47] & 0x18) == 0x18)
+               cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
+       else
+               cr37 |= 0xc0;
+
+       outSISIDXREG(SISCR, 0x36, paneltype);
+       cr37 &= 0xf1;
+       setSISIDXREG(SISCR, 0x37, 0x0c, cr37);
+       orSISIDXREG(SISCR, 0x32, 0x08);
+
+       ivideo->SiS_Pr.PanelSelfDetected = TRUE;
+}
+
+static int __devinit
+SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
     int temp, mytest, result, i, j;
 
@@ -2749,10 +2489,11 @@ static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 tes
        }
        if((result == 0) || (result >= 2)) break;
     }
-    return(result);
+    return result;
 }
 
-static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
+static void __devinit
+SiS_Sense30x(struct sis_video_info *ivideo)
 {
     u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
     u16 svhs=0, svhs_c=0;
@@ -2762,36 +2503,51 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
     char stdstr[] = "sisfb: Detected";
     char tvstr[]  = "TV connected to";
 
-    if(ivideo->vbflags & VB_301) {
+    if(ivideo->vbflags2 & VB2_301) {
        svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
        inSISIDXREG(SISPART4,0x01,myflag);
        if(myflag & 0x04) {
          svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
        }
-    } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
+    } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) {
        svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
-    } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
+    } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) {
        svhs = 0x0200; cvbs = 0x0100;
-    } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
+    } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) {
        svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
-    } else return;
+    } else
+       return;
 
     vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
-    if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+    if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) {
        svhs_c = 0x0408; cvbs_c = 0x0808;
     }
+
     biosflag = 2;
+    if(ivideo->haveXGIROM) {
+       biosflag = ivideo->bios_abase[0x58] & 0x03;
+    } else if(ivideo->newrom) {
+       if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01;
+    } else if(ivideo->sisvga_engine == SIS_300_VGA) {
+       if(ivideo->bios_abase) {
+          biosflag = ivideo->bios_abase[0xfe] & 0x03;
+       }
+    }
 
     if(ivideo->chip == SIS_300) {
        inSISIDXREG(SISSR,0x3b,myflag);
        if(!(myflag & 0x01)) vga2 = vga2_c = 0;
     }
 
+    if(!(ivideo->vbflags2 & VB2_SISVGA2BRIDGE)) {
+       vga2 = vga2_c = 0;
+    }
+
     inSISIDXREG(SISSR,0x1e,backupSR_1e);
     orSISIDXREG(SISSR,0x1e,0x20);
 
     inSISIDXREG(SISPART4,0x0d,backupP4_0d);
-    if(ivideo->vbflags & VB_301C) {
+    if(ivideo->vbflags2 & VB2_30xC) {
        setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
     } else {
        orSISIDXREG(SISPART4,0x0d,0x04);
@@ -2802,11 +2558,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
     outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
 
     inSISIDXREG(SISPART2,0x4d,backupP2_4d);
-    if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+    if(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE) {
        outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
     }
 
-    if(!(ivideo->vbflags & VB_301C)) {
+    if(!(ivideo->vbflags2 & VB2_30xCLV)) {
        SISDoSense(ivideo, 0, 0);
     }
 
@@ -2826,12 +2582,11 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
 
     andSISIDXREG(SISCR, 0x32, 0x3f);
 
-    if(ivideo->vbflags & VB_301C) {
+    if(ivideo->vbflags2 & VB2_30xCLV) {
        orSISIDXREG(SISPART4,0x0d,0x04);
     }
 
-    if((ivideo->sisvga_engine == SIS_315_VGA) &&
-       (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+    if((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
        outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
        if((result = SISDoSense(ivideo, svhs, 0x0604))) {
@@ -2864,7 +2619,7 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
     outSISIDXREG(SISSR,0x1e,backupSR_1e);
 
-    if(ivideo->vbflags & VB_301C) {
+    if(ivideo->vbflags2 & VB2_30xCLV) {
        inSISIDXREG(SISPART2,0x00,biosflag);
        if(biosflag & 0x20) {
           for(myflag = 2; myflag > 0; myflag--) {
@@ -2878,7 +2633,8 @@ static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
 }
 
 /* Determine and detect attached TV's on Chrontel */
-static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
+static void __devinit
+SiS_SenseCh(struct sis_video_info *ivideo)
 {
 #if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)
     u8 temp1, temp2;
@@ -2899,7 +2655,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
        /* See Chrontel TB31 for explanation */
        temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
        if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
-         SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
+         SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e, 0x0b);
          SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
        }
        temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
@@ -2909,15 +2665,15 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
           /* Read power status */
           temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
           if((temp1 & 0x03) != 0x03) {
-               /* Power all outputs */
-               SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
+               /* Power all outputs */
+               SiS_SetCH700x(&ivideo->SiS_Pr, 0x0e,0x0b);
                SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
           }
           /* Sense connected TV devices */
           for(i = 0; i < 3; i++) {
-              SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
+              SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x01);
               SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
-              SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
+              SiS_SetCH700x(&ivideo->SiS_Pr, 0x10, 0x00);
               SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
               temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
               if(!(temp1 & 0x08))       test[i] = 0x02;
@@ -2930,7 +2686,7 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
           else if(test[0] == test[2]) temp1 = test[0];
           else if(test[1] == test[2]) temp1 = test[1];
           else {
-               printk(KERN_INFO
+               printk(KERN_INFO
                        "sisfb: TV detection unreliable - test results varied\n");
                temp1 = test[2];
           }
@@ -2945,11 +2701,11 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
                orSISIDXREG(SISCR, 0x32, 0x01);
                andSISIDXREG(SISCR, 0x32, ~0x06);
           } else {
-               SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
+               SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
                andSISIDXREG(SISCR, 0x32, ~0x07);
           }
        } else if(temp1 == 0) {
-         SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
+         SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x0e, 0x01, 0xF8);
          andSISIDXREG(SISCR, 0x32, ~0x07);
        }
        /* Set general purpose IO for Chrontel communication */
@@ -2960,19 +2716,19 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
 
 #ifdef CONFIG_FB_SIS_315
        ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;           /* Chrontel 7019 */
-        temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
-       SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
+       temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+       SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, 0x20);
        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
        temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
        temp2 |= 0x01;
-       SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+       SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
        temp2 ^= 0x01;
-       SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+       SiS_SetCH701x(&ivideo->SiS_Pr, 0x20, temp2);
        SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
        temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
-       SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
-        temp1 = 0;
+       SiS_SetCH701x(&ivideo->SiS_Pr, 0x49, temp1);
+       temp1 = 0;
        if(temp2 & 0x02) temp1 |= 0x01;
        if(temp2 & 0x10) temp1 |= 0x01;
        if(temp2 & 0x04) temp1 |= 0x02;
@@ -2983,18 +2739,18 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
             ivideo->vbflags |= TV_AVIDEO;
             orSISIDXREG(SISCR, 0x32, 0x01);
             andSISIDXREG(SISCR, 0x32, ~0x06);
-             break;
+            break;
        case 0x02:
             printk(KERN_INFO "%s SVIDEO output\n", stdstr);
             ivideo->vbflags |= TV_SVIDEO;
             orSISIDXREG(SISCR, 0x32, 0x02);
             andSISIDXREG(SISCR, 0x32, ~0x05);
-             break;
+            break;
        case 0x04:
             printk(KERN_INFO "%s SCART output\n", stdstr);
             orSISIDXREG(SISCR, 0x32, 0x04);
             andSISIDXREG(SISCR, 0x32, ~0x03);
-             break;
+            break;
        default:
             andSISIDXREG(SISCR, 0x32, ~0x07);
        }
@@ -3002,165 +2758,589 @@ static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
     }
 }
 
-/* ------------------------ Heap routines -------------------------- */
-
-static u32 __devinit
-sisfb_getheapstart(struct sis_video_info *ivideo)
+static void __devinit
+sisfb_get_VB_type(struct sis_video_info *ivideo)
 {
-       u32 ret = ivideo->sisfb_parm_mem * 1024;
-       u32 max = ivideo->video_size - ivideo->hwcursor_size;
-       u32 def;
+       char stdstr[]    = "sisfb: Detected";
+       char bridgestr[] = "video bridge";
+       u8 vb_chipid;
+       u8 reg;
 
-       /* Calculate heap start = end of memory for console
-        *
-        * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
-        * C = console, D = heap, H = HWCursor, Q = cmd-queue
-        *
-        * Basically given by "mem" parameter
-        *
-        * maximum = videosize - cmd_queue - hwcursor
-        *           (results in a heap of size 0)
-        * default = SiS 300: depends on videosize
-        *           SiS 315/330: 32k below max
-        */
+       /* No CRT2 on XGI Z7 */
+       if(ivideo->chip == XGI_20)
+               return;
 
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-          max -= TURBO_QUEUE_AREA_SIZE;
-          if(ivideo->video_size > 0x1000000) {
-             def = 0xc00000;
-          } else if(ivideo->video_size > 0x800000) {
-             def = 0x800000;
-          } else {
-             def = 0x400000;
-          }
-       } else {
-          max -= COMMAND_QUEUE_AREA_SIZE;
-          def = max - 0x8000;
+       inSISIDXREG(SISPART4, 0x00, vb_chipid);
+       switch(vb_chipid) {
+       case 0x01:
+               inSISIDXREG(SISPART4, 0x01, reg);
+               if(reg < 0xb0) {
+                       ivideo->vbflags |= VB_301;      /* Deprecated */
+                       ivideo->vbflags2 |= VB2_301;
+                       printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
+               } else if(reg < 0xc0) {
+                       ivideo->vbflags |= VB_301B;     /* Deprecated */
+                       ivideo->vbflags2 |= VB2_301B;
+                       inSISIDXREG(SISPART4,0x23,reg);
+                       if(!(reg & 0x02)) {
+                          ivideo->vbflags |= VB_30xBDH;        /* Deprecated */
+                          ivideo->vbflags2 |= VB2_30xBDH;
+                          printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
+                       } else {
+                          printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
+                       }
+               } else if(reg < 0xd0) {
+                       ivideo->vbflags |= VB_301C;     /* Deprecated */
+                       ivideo->vbflags2 |= VB2_301C;
+                       printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
+               } else if(reg < 0xe0) {
+                       ivideo->vbflags |= VB_301LV;    /* Deprecated */
+                       ivideo->vbflags2 |= VB2_301LV;
+                       printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
+               } else if(reg <= 0xe1) {
+                       inSISIDXREG(SISPART4,0x39,reg);
+                       if(reg == 0xff) {
+                          ivideo->vbflags |= VB_302LV; /* Deprecated */
+                          ivideo->vbflags2 |= VB2_302LV;
+                          printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
+                       } else {
+                          ivideo->vbflags |= VB_301C;  /* Deprecated */
+                          ivideo->vbflags2 |= VB2_301C;
+                          printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0
+                          ivideo->vbflags |= VB_302ELV;        /* Deprecated */
+                          ivideo->vbflags2 |= VB2_302ELV;
+                          printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif
+                       }
+               }
+               break;
+       case 0x02:
+               ivideo->vbflags |= VB_302B;     /* Deprecated */
+               ivideo->vbflags2 |= VB2_302B;
+               printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
+               break;
        }
 
-        if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
-          ret = def;
-        }
-
-       return ret;
-}
-
-static int __devinit
-sisfb_heap_init(struct sis_video_info *ivideo)
+       if((!(ivideo->vbflags2 & VB2_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+               inSISIDXREG(SISCR, 0x37, reg);
+               reg &= SIS_EXTERNAL_CHIP_MASK;
+               reg >>= 1;
+               if(ivideo->sisvga_engine == SIS_300_VGA) {
+#ifdef CONFIG_FB_SIS_300
+                       switch(reg) {
+                          case SIS_EXTERNAL_CHIP_LVDS:
+                               ivideo->vbflags |= VB_LVDS;     /* Deprecated */
+                               ivideo->vbflags2 |= VB2_LVDS;
+                               break;
+                          case SIS_EXTERNAL_CHIP_TRUMPION:
+                               ivideo->vbflags |= (VB_LVDS | VB_TRUMPION);     /* Deprecated */
+                               ivideo->vbflags2 |= (VB2_LVDS | VB2_TRUMPION);
+                               break;
+                          case SIS_EXTERNAL_CHIP_CHRONTEL:
+                               ivideo->vbflags |= VB_CHRONTEL; /* Deprecated */
+                               ivideo->vbflags2 |= VB2_CHRONTEL;
+                               break;
+                          case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
+                               ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);     /* Deprecated */
+                               ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+                               break;
+                       }
+                       if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 1;
+#endif
+               } else if(ivideo->chip < SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+                       switch (reg) {
+                          case SIS310_EXTERNAL_CHIP_LVDS:
+                               ivideo->vbflags |= VB_LVDS;     /* Deprecated */
+                               ivideo->vbflags2 |= VB2_LVDS;
+                               break;
+                          case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
+                               ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);     /* Deprecated */
+                               ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+                               break;
+                       }
+                       if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+               } else if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315
+                       inSISIDXREG(SISCR, 0x38, reg);
+                       reg >>= 5;
+                       switch(reg) {
+                          case 0x02:
+                               ivideo->vbflags |= VB_LVDS;     /* Deprecated */
+                               ivideo->vbflags2 |= VB2_LVDS;
+                               break;
+                          case 0x03:
+                               ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);     /* Deprecated */
+                               ivideo->vbflags2 |= (VB2_LVDS | VB2_CHRONTEL);
+                               break;
+                          case 0x04:
+                               ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);     /* Deprecated */
+                               ivideo->vbflags2 |= (VB2_LVDS | VB2_CONEXANT);
+                               break;
+                       }
+                       if(ivideo->vbflags2 & VB2_CHRONTEL) ivideo->chronteltype = 2;
+#endif
+               }
+               if(ivideo->vbflags2 & VB2_LVDS) {
+                  printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+               }
+               if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & VB2_TRUMPION)) {
+                  printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+               }
+               if(ivideo->vbflags2 & VB2_CHRONTEL) {
+                  printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+               }
+               if((ivideo->chip >= SIS_661) && (ivideo->vbflags2 & VB2_CONEXANT)) {
+                  printk(KERN_INFO "%s Conexant external device\n", stdstr);
+               }
+       }
+
+       if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+               SiS_SenseLCD(ivideo);
+               SiS_Sense30x(ivideo);
+       } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+               SiS_SenseCh(ivideo);
+       }
+}
+
+/* ---------- Engine initialization routines ------------ */
+
+static void
+sisfb_engine_init(struct sis_video_info *ivideo)
 {
-     SIS_OH *poh;
 
-     ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
+       /* Initialize command queue (we use MMIO only) */
 
-     ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
-     ivideo->sisfb_heap_end   = ivideo->video_vbase + ivideo->video_size;
+       /* BEFORE THIS IS CALLED, THE ENGINES *MUST* BE SYNC'ED */
 
-     /* Initialize command queue (We use MMIO only) */
+       ivideo->caps &= ~(TURBO_QUEUE_CAP    |
+                         MMIO_CMD_QUEUE_CAP |
+                         VM_CMD_QUEUE_CAP   |
+                         AGP_CMD_QUEUE_CAP);
+
+#ifdef CONFIG_FB_SIS_300
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
+               u32 tqueue_pos;
+               u8 tq_state;
+
+               tqueue_pos = (ivideo->video_size - ivideo->cmdQueueSize) / (64 * 1024);
+
+               inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+               tq_state |= 0xf0;
+               tq_state &= 0xfc;
+               tq_state |= (u8)(tqueue_pos >> 8);
+               outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+
+               outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+
+               ivideo->caps |= TURBO_QUEUE_CAP;
+       }
+#endif
 
 #ifdef CONFIG_FB_SIS_315
-     if(ivideo->sisvga_engine == SIS_315_VGA) {
-        u32 tempq = 0;
-       u8  temp = 0;
+       if(ivideo->sisvga_engine == SIS_315_VGA) {
+               u32 tempq = 0, templ;
+               u8  temp;
+
+               if(ivideo->chip == XGI_20) {
+                       switch(ivideo->cmdQueueSize) {
+                       case (64 * 1024):
+                               temp = SIS_CMD_QUEUE_SIZE_Z7_64k;
+                               break;
+                       case (128 * 1024):
+                       default:
+                               temp = SIS_CMD_QUEUE_SIZE_Z7_128k;
+                       }
+               } else {
+                       switch(ivideo->cmdQueueSize) {
+                       case (4 * 1024 * 1024):
+                               temp = SIS_CMD_QUEUE_SIZE_4M;
+                               break;
+                       case (2 * 1024 * 1024):
+                               temp = SIS_CMD_QUEUE_SIZE_2M;
+                               break;
+                       case (1 * 1024 * 1024):
+                               temp = SIS_CMD_QUEUE_SIZE_1M;
+                               break;
+                       default:
+                       case (512 * 1024):
+                               temp = SIS_CMD_QUEUE_SIZE_512k;
+                       }
+               }
+
+               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+               if((ivideo->chip >= XGI_40) && ivideo->modechanged) {
+                       /* Must disable dual pipe on XGI_40. Can't do
+                        * this in MMIO mode, because it requires
+                        * setting/clearing a bit in the MMIO fire trigger
+                        * register.
+                        */
+                       if(!((templ = MMIO_IN32(ivideo->mmio_vbase, 0x8240)) & (1 << 10))) {
+
+                               MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, 0);
+
+                               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, (temp | SIS_VRAM_CMDQUEUE_ENABLE));
+
+                               tempq = MMIO_IN32(ivideo->mmio_vbase, Q_READ_PTR);
+                               MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, tempq);
 
-        ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+                               tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+                               MMIO_OUT32(ivideo->mmio_vbase, Q_BASE_ADDR, tempq);
 
-       outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-       outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+                               writel(0x16800000 + 0x8240, ivideo->video_vbase + tempq);
+                               writel(templ | (1 << 10), ivideo->video_vbase + tempq + 4);
+                               writel(0x168F0000, ivideo->video_vbase + tempq + 8);
+                               writel(0x168F0000, ivideo->video_vbase + tempq + 12);
+
+                               MMIO_OUT32(ivideo->mmio_vbase, Q_WRITE_PTR, (tempq + 16));
+
+                               sisfb_syncaccel(ivideo);
+
+                               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+                       }
+               }
+
+               tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+               MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+
+               temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+               outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+
+               tempq = (u32)(ivideo->video_size - ivideo->cmdQueueSize);
+               MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
+
+               ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+       }
+#endif
+
+       ivideo->engineok = 1;
+}
+
+static void __devinit
+sisfb_detect_lcd_type(struct sis_video_info *ivideo)
+{
+       u8 reg;
+       int i;
 
-       tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
-       MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+       inSISIDXREG(SISCR, 0x36, reg);
+       reg &= 0x0f;
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
+               ivideo->CRT2LCDType = sis300paneltype[reg];
+       } else if(ivideo->chip >= SIS_661) {
+               ivideo->CRT2LCDType = sis661paneltype[reg];
+       } else {
+               ivideo->CRT2LCDType = sis310paneltype[reg];
+               if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+                       if((ivideo->CRT2LCDType != LCD_320x240_2) &&
+                          (ivideo->CRT2LCDType != LCD_320x240_3)) {
+                               ivideo->CRT2LCDType = LCD_320x240;
+                       }
+               }
+       }
 
-       temp = SIS_CMD_QUEUE_SIZE_512k;
-       temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-       outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+       if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
+               /* For broken BIOSes: Assume 1024x768, RGB18 */
+               ivideo->CRT2LCDType = LCD_1024x768;
+               setSISIDXREG(SISCR,0x36,0xf0,0x02);
+               setSISIDXREG(SISCR,0x37,0xee,0x01);
+               printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
+       }
 
-       tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
-       MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
+       for(i = 0; i < SIS_LCD_NUMBER; i++) {
+               if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
+                       ivideo->lcdxres = sis_lcd_data[i].xres;
+                       ivideo->lcdyres = sis_lcd_data[i].yres;
+                       ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+                       break;
+               }
+       }
 
-       ivideo->caps |= MMIO_CMD_QUEUE_CAP;
-     }
+#ifdef CONFIG_FB_SIS_300
+       if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+               ivideo->lcdxres = 1360; ivideo->lcdyres = 1024;
+               ivideo->lcddefmodeidx = DEFAULT_MODE_1360;
+       } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+               ivideo->lcdxres =  848; ivideo->lcdyres =  480;
+               ivideo->lcddefmodeidx = DEFAULT_MODE_848;
+       } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL856) {
+               ivideo->lcdxres =  856; ivideo->lcdyres =  480;
+               ivideo->lcddefmodeidx = DEFAULT_MODE_856;
+       }
 #endif
 
+       printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
+                       ivideo->lcdxres, ivideo->lcdyres);
+}
+
+static void __devinit
+sisfb_save_pdc_emi(struct sis_video_info *ivideo)
+{
 #ifdef CONFIG_FB_SIS_300
-     if(ivideo->sisvga_engine == SIS_300_VGA) {
-       unsigned long tqueue_pos;
-       u8 tq_state;
+       /* Save the current PanelDelayCompensation if the LCD is currently used */
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
+               if(ivideo->vbflags2 & (VB2_LVDS | VB2_30xBDH)) {
+                       int tmp;
+                       inSISIDXREG(SISCR,0x30,tmp);
+                       if(tmp & 0x20) {
+                               /* Currently on LCD? If yes, read current pdc */
+                               inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+                               ivideo->detectedpdc &= 0x3c;
+                               if(ivideo->SiS_Pr.PDC == -1) {
+                                       /* Let option override detection */
+                                       ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+                               }
+                               printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
+                                       ivideo->detectedpdc);
+                       }
+                       if((ivideo->SiS_Pr.PDC != -1) &&
+                          (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+                               printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
+                                       ivideo->SiS_Pr.PDC);
+                       }
+               }
+       }
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+       if(ivideo->sisvga_engine == SIS_315_VGA) {
 
-       ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+               /* Try to find about LCDA */
+               if(ivideo->vbflags2 & VB2_SISLCDABRIDGE) {
+                       int tmp;
+                       inSISIDXREG(SISPART1,0x13,tmp);
+                       if(tmp & 0x04) {
+                               ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+                               ivideo->detectedlcda = 0x03;
+                       }
+               }
 
-       tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+               /* Save PDC */
+               if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) {
+                       int tmp;
+                       inSISIDXREG(SISCR,0x30,tmp);
+                       if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+                               /* Currently on LCD? If yes, read current pdc */
+                               u8 pdc;
+                               inSISIDXREG(SISPART1,0x2D,pdc);
+                               ivideo->detectedpdc  = (pdc & 0x0f) << 1;
+                               ivideo->detectedpdca = (pdc & 0xf0) >> 3;
+                               inSISIDXREG(SISPART1,0x35,pdc);
+                               ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
+                               inSISIDXREG(SISPART1,0x20,pdc);
+                               ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+                               if(ivideo->newrom) {
+                                       /* New ROM invalidates other PDC resp. */
+                                       if(ivideo->detectedlcda != 0xff) {
+                                               ivideo->detectedpdc = 0xff;
+                                       } else {
+                                               ivideo->detectedpdca = 0xff;
+                                       }
+                               }
+                               if(ivideo->SiS_Pr.PDC == -1) {
+                                       if(ivideo->detectedpdc != 0xff) {
+                                               ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
+                                       }
+                               }
+                               if(ivideo->SiS_Pr.PDCA == -1) {
+                                       if(ivideo->detectedpdca != 0xff) {
+                                               ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
+                                       }
+                               }
+                               if(ivideo->detectedpdc != 0xff) {
+                                       printk(KERN_INFO
+                                               "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
+                                               ivideo->detectedpdc);
+                               }
+                               if(ivideo->detectedpdca != 0xff) {
+                                       printk(KERN_INFO
+                                               "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
+                                               ivideo->detectedpdca);
+                               }
+                       }
 
-       inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-       tq_state |= 0xf0;
-       tq_state &= 0xfc;
-       tq_state |= (u8)(tqueue_pos >> 8);
-       outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+                       /* Save EMI */
+                       if(ivideo->vbflags2 & VB2_SISEMIBRIDGE) {
+                               inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
+                               inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
+                               inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
+                               inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+                               ivideo->SiS_Pr.HaveEMI = TRUE;
+                               if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+                                       ivideo->SiS_Pr.HaveEMILCD = TRUE;
+                               }
+                       }
+               }
 
-       outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
+               /* Let user override detected PDCs (all bridges) */
+               if(ivideo->vbflags2 & VB2_30xBLV) {
+                       if((ivideo->SiS_Pr.PDC != -1) &&
+                          (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
+                               printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
+                                       ivideo->SiS_Pr.PDC);
+                       }
+                       if((ivideo->SiS_Pr.PDCA != -1) &&
+                          (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
+                               printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
+                                ivideo->SiS_Pr.PDCA);
+                       }
+               }
 
-       ivideo->caps |= TURBO_QUEUE_CAP;
-     }
+       }
 #endif
+}
+
+/* -------------------- Memory manager routines ---------------------- */
+
+static u32 __devinit
+sisfb_getheapstart(struct sis_video_info *ivideo)
+{
+       u32 ret = ivideo->sisfb_parm_mem * 1024;
+       u32 maxoffs = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+       u32 def;
+
+       /* Calculate heap start = end of memory for console
+        *
+        * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+        * C = console, D = heap, H = HWCursor, Q = cmd-queue
+        *
+        * On 76x in UMA+LFB mode, the layout is as follows:
+        * DDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCCCCCHHHHQQQQQQQQQQQ
+        * where the heap is the entire UMA area, eventually
+        * into the LFB area if the given mem parameter is
+        * higher than the size of the UMA memory.
+        *
+        * Basically given by "mem" parameter
+        *
+        * maximum = videosize - cmd_queue - hwcursor
+        *           (results in a heap of size 0)
+        * default = SiS 300: depends on videosize
+        *           SiS 315/330/340/XGI: 32k below max
+        */
+
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
+               if(ivideo->video_size > 0x1000000) {
+                       def = 0xc00000;
+               } else if(ivideo->video_size > 0x800000) {
+                       def = 0x800000;
+               } else {
+                       def = 0x400000;
+               }
+       } else if(ivideo->UMAsize && ivideo->LFBsize) {
+               ret = def = 0;
+       } else {
+               def = maxoffs - 0x8000;
+       }
+
+       /* Use default for secondary card for now (FIXME) */
+       if((!ret) || (ret > maxoffs) || (ivideo->cardnumber != 0))
+               ret = def;
+
+       return ret;
+}
+
+static u32 __devinit
+sisfb_getheapsize(struct sis_video_info *ivideo)
+{
+       u32 max = ivideo->video_size - ivideo->hwcursor_size - ivideo->cmdQueueSize;
+       u32 ret = 0;
+
+       if(ivideo->UMAsize && ivideo->LFBsize) {
+               if( (!ivideo->sisfb_parm_mem)                   ||
+                   ((ivideo->sisfb_parm_mem * 1024) > max)     ||
+                   ((max - (ivideo->sisfb_parm_mem * 1024)) < ivideo->UMAsize) ) {
+                       ret = ivideo->UMAsize;
+                       max -= ivideo->UMAsize;
+               } else {
+                       ret = max - (ivideo->sisfb_parm_mem * 1024);
+                       max = ivideo->sisfb_parm_mem * 1024;
+               }
+               ivideo->video_offset = ret;
+               ivideo->sisfb_mem = max;
+       } else {
+               ret = max - ivideo->heapstart;
+               ivideo->sisfb_mem = ivideo->heapstart;
+       }
 
-     /* Reserve memory for the HWCursor */
-     ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
-     ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
-     ivideo->caps |= HW_CURSOR_CAP;
+       return ret;
+}
 
-     ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
+static int __devinit
+sisfb_heap_init(struct sis_video_info *ivideo)
+{
+       struct SIS_OH *poh;
 
-     if(ivideo->cardnumber == 0) {
+       ivideo->video_offset = 0;
+       if(ivideo->sisfb_parm_mem) {
+               if( (ivideo->sisfb_parm_mem < (2 * 1024 * 1024)) ||
+                   (ivideo->sisfb_parm_mem > ivideo->video_size) ) {
+                       ivideo->sisfb_parm_mem = 0;
+               }
+       }
 
-       printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
-               (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
+       ivideo->heapstart = sisfb_getheapstart(ivideo);
+       ivideo->sisfb_heap_size = sisfb_getheapsize(ivideo);
 
-       sisfb_heap.vinfo = ivideo;
+       ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+       ivideo->sisfb_heap_end   = ivideo->sisfb_heap_start + ivideo->sisfb_heap_size;
 
-       sisfb_heap.poha_chain = NULL;
-       sisfb_heap.poh_freelist = NULL;
+       printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+               (int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
 
-       poh = sisfb_poh_new_node();
-       if(poh == NULL) return 1;
+       ivideo->sisfb_heap.vinfo = ivideo;
 
-       poh->poh_next = &sisfb_heap.oh_free;
-       poh->poh_prev = &sisfb_heap.oh_free;
-       poh->size = ivideo->sisfb_heap_size;
-       poh->offset = ivideo->heapstart;
+       ivideo->sisfb_heap.poha_chain = NULL;
+       ivideo->sisfb_heap.poh_freelist = NULL;
 
-       sisfb_heap.oh_free.poh_next = poh;
-       sisfb_heap.oh_free.poh_prev = poh;
-       sisfb_heap.oh_free.size = 0;
-       sisfb_heap.max_freesize = poh->size;
+       poh = sisfb_poh_new_node(&ivideo->sisfb_heap);
+       if(poh == NULL)
+               return 1;
 
-       sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
-       sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
-       sisfb_heap.oh_used.size = SENTINEL;
+       poh->poh_next = &ivideo->sisfb_heap.oh_free;
+       poh->poh_prev = &ivideo->sisfb_heap.oh_free;
+       poh->size = ivideo->sisfb_heap_size;
+       poh->offset = ivideo->heapstart;
 
-     } else {
+       ivideo->sisfb_heap.oh_free.poh_next = poh;
+       ivideo->sisfb_heap.oh_free.poh_prev = poh;
+       ivideo->sisfb_heap.oh_free.size = 0;
+       ivideo->sisfb_heap.max_freesize = poh->size;
 
-        printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
+       ivideo->sisfb_heap.oh_used.poh_next = &ivideo->sisfb_heap.oh_used;
+       ivideo->sisfb_heap.oh_used.poh_prev = &ivideo->sisfb_heap.oh_used;
+       ivideo->sisfb_heap.oh_used.size = SENTINEL;
 
-     }
+       if(ivideo->cardnumber == 0) {
+               /* For the first card, make this heap the "global" one
+                * for old DRM (which could handle only one card)
+                */
+               sisfb_heap = &ivideo->sisfb_heap;
+       }
 
-     return 0;
+       return 0;
 }
 
-static SIS_OH *
-sisfb_poh_new_node(void)
+static struct SIS_OH *
+sisfb_poh_new_node(struct SIS_HEAP *memheap)
 {
-       int           i;
-       unsigned long cOhs;
-       SIS_OHALLOC   *poha;
-       SIS_OH        *poh;
+       struct SIS_OHALLOC      *poha;
+       struct SIS_OH           *poh;
+       unsigned long           cOhs;
+       int                     i;
 
-       if(sisfb_heap.poh_freelist == NULL) {
+       if(memheap->poh_freelist == NULL) {
                poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
-               if(!poha) return NULL;
+               if(!poha)
+                       return NULL;
 
-               poha->poha_next = sisfb_heap.poha_chain;
-               sisfb_heap.poha_chain = poha;
+               poha->poha_next = memheap->poha_chain;
+               memheap->poha_chain = poha;
 
-               cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
+               cOhs = (SIS_OH_ALLOC_SIZE - sizeof(struct SIS_OHALLOC)) / sizeof(struct SIS_OH) + 1;
 
                poh = &poha->aoh[0];
                for(i = cOhs - 1; i != 0; i--) {
@@ -3169,32 +3349,32 @@ sisfb_poh_new_node(void)
                }
 
                poh->poh_next = NULL;
-               sisfb_heap.poh_freelist = &poha->aoh[0];
+               memheap->poh_freelist = &poha->aoh[0];
        }
 
-       poh = sisfb_heap.poh_freelist;
-       sisfb_heap.poh_freelist = poh->poh_next;
+       poh = memheap->poh_freelist;
+       memheap->poh_freelist = poh->poh_next;
 
-       return (poh);
+       return poh;
 }
 
-static SIS_OH *
-sisfb_poh_allocate(u32 size)
+static struct SIS_OH *
+sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size)
 {
-       SIS_OH *pohThis;
-       SIS_OH *pohRoot;
-       int     bAllocated = 0;
+       struct SIS_OH   *pohThis;
+       struct SIS_OH   *pohRoot;
+       int             bAllocated = 0;
 
-       if(size > sisfb_heap.max_freesize) {
+       if(size > memheap->max_freesize) {
                DPRINTK("sisfb: Can't allocate %dk video memory\n",
                        (unsigned int) size / 1024);
-               return (NULL);
+               return NULL;
        }
 
-       pohThis = sisfb_heap.oh_free.poh_next;
+       pohThis = memheap->oh_free.poh_next;
 
-       while(pohThis != &sisfb_heap.oh_free) {
-               if (size <= pohThis->size) {
+       while(pohThis != &memheap->oh_free) {
+               if(size <= pohThis->size) {
                        bAllocated = 1;
                        break;
                }
@@ -3204,18 +3384,16 @@ sisfb_poh_allocate(u32 size)
        if(!bAllocated) {
                DPRINTK("sisfb: Can't allocate %dk video memory\n",
                        (unsigned int) size / 1024);
-               return (NULL);
+               return NULL;
        }
 
        if(size == pohThis->size) {
                pohRoot = pohThis;
                sisfb_delete_node(pohThis);
        } else {
-               pohRoot = sisfb_poh_new_node();
-
-               if(pohRoot == NULL) {
-                       return (NULL);
-               }
+               pohRoot = sisfb_poh_new_node(memheap);
+               if(pohRoot == NULL)
+                       return NULL;
 
                pohRoot->offset = pohThis->offset;
                pohRoot->size = size;
@@ -3224,33 +3402,25 @@ sisfb_poh_allocate(u32 size)
                pohThis->size -= size;
        }
 
-       sisfb_heap.max_freesize -= size;
+       memheap->max_freesize -= size;
 
-       pohThis = &sisfb_heap.oh_used;
+       pohThis = &memheap->oh_used;
        sisfb_insert_node(pohThis, pohRoot);
 
-       return (pohRoot);
+       return pohRoot;
 }
 
 static void
-sisfb_delete_node(SIS_OH *poh)
+sisfb_delete_node(struct SIS_OH *poh)
 {
-       SIS_OH *poh_prev;
-       SIS_OH *poh_next;
-
-       poh_prev = poh->poh_prev;
-       poh_next = poh->poh_next;
-
-       poh_prev->poh_next = poh_next;
-       poh_next->poh_prev = poh_prev;
+       poh->poh_prev->poh_next = poh->poh_next;
+       poh->poh_next->poh_prev = poh->poh_prev;
 }
 
 static void
-sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
+sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh)
 {
-       SIS_OH *pohTemp;
-
-       pohTemp = pohList->poh_next;
+       struct SIS_OH *pohTemp = pohList->poh_next;
 
        pohList->poh_next = poh;
        pohTemp->poh_prev = poh;
@@ -3259,20 +3429,20 @@ sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh)
        poh->poh_next = pohTemp;
 }
 
-static SIS_OH *
-sisfb_poh_free(u32 base)
+static struct SIS_OH *
+sisfb_poh_free(struct SIS_HEAP *memheap, u32 base)
 {
-       SIS_OH *pohThis;
-       SIS_OH *poh_freed;
-       SIS_OH *poh_prev;
-       SIS_OH *poh_next;
-       u32     ulUpper;
-       u32     ulLower;
-       int     foundNode = 0;
+       struct SIS_OH *pohThis;
+       struct SIS_OH *poh_freed;
+       struct SIS_OH *poh_prev;
+       struct SIS_OH *poh_next;
+       u32    ulUpper;
+       u32    ulLower;
+       int    foundNode = 0;
 
-       poh_freed = sisfb_heap.oh_used.poh_next;
+       poh_freed = memheap->oh_used.poh_next;
 
-       while(poh_freed != &sisfb_heap.oh_used) {
+       while(poh_freed != &memheap->oh_used) {
                if(poh_freed->offset == base) {
                        foundNode = 1;
                        break;
@@ -3281,17 +3451,18 @@ sisfb_poh_free(u32 base)
                poh_freed = poh_freed->poh_next;
        }
 
-       if(!foundNode) return(NULL);
+       if(!foundNode)
+               return NULL;
 
-       sisfb_heap.max_freesize += poh_freed->size;
+       memheap->max_freesize += poh_freed->size;
 
        poh_prev = poh_next = NULL;
        ulUpper = poh_freed->offset + poh_freed->size;
        ulLower = poh_freed->offset;
 
-       pohThis = sisfb_heap.oh_free.poh_next;
+       pohThis = memheap->oh_free.poh_next;
 
-       while(pohThis != &sisfb_heap.oh_free) {
+       while(pohThis != &memheap->oh_free) {
                if(pohThis->offset == ulUpper) {
                        poh_next = pohThis;
                } else if((pohThis->offset + pohThis->size) == ulLower) {
@@ -3305,70 +3476,88 @@ sisfb_poh_free(u32 base)
        if(poh_prev && poh_next) {
                poh_prev->size += (poh_freed->size + poh_next->size);
                sisfb_delete_node(poh_next);
-               sisfb_free_node(poh_freed);
-               sisfb_free_node(poh_next);
-               return(poh_prev);
+               sisfb_free_node(memheap, poh_freed);
+               sisfb_free_node(memheap, poh_next);
+               return poh_prev;
        }
 
        if(poh_prev) {
                poh_prev->size += poh_freed->size;
-               sisfb_free_node(poh_freed);
-               return(poh_prev);
+               sisfb_free_node(memheap, poh_freed);
+               return poh_prev;
        }
 
        if(poh_next) {
                poh_next->size += poh_freed->size;
                poh_next->offset = poh_freed->offset;
-               sisfb_free_node(poh_freed);
-               return(poh_next);
+               sisfb_free_node(memheap, poh_freed);
+               return poh_next;
        }
 
-       sisfb_insert_node(&sisfb_heap.oh_free, poh_freed);
+       sisfb_insert_node(&memheap->oh_free, poh_freed);
 
-       return(poh_freed);
+       return poh_freed;
 }
 
 static void
-sisfb_free_node(SIS_OH *poh)
+sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh)
 {
-       if(poh == NULL) return;
+       if(poh == NULL)
+               return;
 
-       poh->poh_next = sisfb_heap.poh_freelist;
-       sisfb_heap.poh_freelist = poh;
+       poh->poh_next = memheap->poh_freelist;
+       memheap->poh_freelist = poh;
 }
 
-void
-sis_malloc(struct sis_memreq *req)
+static void
+sis_int_malloc(struct sis_video_info *ivideo, struct sis_memreq *req)
 {
-       struct sis_video_info *ivideo = sisfb_heap.vinfo;
-       SIS_OH *poh = NULL;
+       struct SIS_OH *poh = NULL;
 
-       if((ivideo) && (!ivideo->havenoheap)) {
-          poh = sisfb_poh_allocate((u32)req->size);
-       }
+       if((ivideo) && (ivideo->sisfb_id == SISFB_ID) && (!ivideo->havenoheap))
+               poh = sisfb_poh_allocate(&ivideo->sisfb_heap, (u32)req->size);
 
        if(poh == NULL) {
-          req->offset = req->size = 0;
-          DPRINTK("sisfb: Video RAM allocation failed\n");
+               req->offset = req->size = 0;
+               DPRINTK("sisfb: Video RAM allocation failed\n");
        } else {
-          req->offset = poh->offset;
-          req->size = poh->size;
-          DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
-                   (poh->offset + ivideo->video_vbase));
+               req->offset = poh->offset;
+               req->size = poh->size;
+               DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+                       (poh->offset + ivideo->video_vbase));
        }
 }
 
-/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+void
+sis_malloc(struct sis_memreq *req)
+{
+       struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+       if(&ivideo->sisfb_heap == sisfb_heap)
+               sis_int_malloc(ivideo, req);
+       else
+               req->offset = req->size = 0;
+}
 
 void
-sis_free(u32 base)
+sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req)
+{
+       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+       sis_int_malloc(ivideo, req);
+}
+
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+
+static void
+sis_int_free(struct sis_video_info *ivideo, u32 base)
 {
-       struct sis_video_info *ivideo = sisfb_heap.vinfo;
-       SIS_OH *poh;
+       struct SIS_OH *poh;
 
-       if((!ivideo) || (ivideo->havenoheap)) return;
+       if((!ivideo) || (ivideo->sisfb_id != SISFB_ID) || (ivideo->havenoheap))
+               return;
 
-       poh = sisfb_poh_free((u32)base);
+       poh = sisfb_poh_free(&ivideo->sisfb_heap, base);
 
        if(poh == NULL) {
                DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3376,8 +3565,62 @@ sis_free(u32 base)
        }
 }
 
+void
+sis_free(u32 base)
+{
+       struct sis_video_info *ivideo = sisfb_heap->vinfo;
+
+       sis_int_free(ivideo, base);
+}
+
+void
+sis_free_new(struct pci_dev *pdev, u32 base)
+{
+       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+
+       sis_int_free(ivideo, base);
+}
+
 /* --------------------- SetMode routines ------------------------- */
 
+static void
+sisfb_check_engine_and_sync(struct sis_video_info *ivideo)
+{
+       u8 cr30, cr31;
+
+       /* Check if MMIO and engines are enabled,
+        * and sync in case they are. Can't use
+        * ivideo->accel here, as this might have
+        * been changed before this is called.
+        */
+       inSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, cr30);
+       inSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, cr31);
+       /* MMIO and 2D/3D engine enabled? */
+       if((cr30 & SIS_MEM_MAP_IO_ENABLE) && (cr31 & 0x42)) {
+#ifdef CONFIG_FB_SIS_300
+               if(ivideo->sisvga_engine == SIS_300_VGA) {
+                       /* Don't care about TurboQueue. It's
+                        * enough to know that the engines
+                        * are enabled
+                        */
+                       sisfb_syncaccel(ivideo);
+               }
+#endif
+#ifdef CONFIG_FB_SIS_315
+               if(ivideo->sisvga_engine == SIS_315_VGA) {
+                       /* Check that any queue mode is
+                        * enabled, and that the queue
+                        * is not in the state of "reset"
+                        */
+                       inSISIDXREG(SISSR, 0x26, cr30);
+                       if((cr30 & 0xe0) && (!(cr30 & 0x01))) {
+                               sisfb_syncaccel(ivideo);
+                       }
+               }
+#endif
+       }
+}
+
 static void
 sisfb_pre_setmode(struct sis_video_info *ivideo)
 {
@@ -3386,6 +3629,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
 
        ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
 
+       outSISIDXREG(SISSR, 0x05, 0x86);
+
        inSISIDXREG(SISCR, 0x31, cr31);
        cr31 &= ~0x60;
        cr31 |= 0x04;
@@ -3413,41 +3658,43 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
 
        SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
        SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+       ivideo->curFSTN = ivideo->curDSTN = 0;
 
        switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 
           case CRT2_TV:
              cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
-             if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
+             if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) {
 #ifdef CONFIG_FB_SIS_315
-                if(ivideo->chip >= SIS_661) {
-                   cr38 |= 0x04;
-                   if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
+                if(ivideo->chip >= SIS_661) {
+                   cr38 |= 0x04;
+                   if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
                    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
                    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
                    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
                    cr35 &= ~0x01;
                    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
-                } else if(ivideo->sisvga_engine == SIS_315_VGA) {
-                   cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+                } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+                   cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
                    cr38 |= 0x08;
-                   if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
+                   if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
                    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
                    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
                    cr31 &= ~0x01;
                    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
-                }
-#endif
-             } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
-                if(ivideo->chip >= SIS_661) {
-                   cr38 |= 0x04;
-                   cr35 |= 0x60;
-                } else {
-                   cr30 |= 0x80;
-                }
+                }
+#endif
+             } else if((ivideo->vbflags & TV_HIVISION) &&
+                               (ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) {
+                if(ivideo->chip >= SIS_661) {
+                   cr38 |= 0x04;
+                   cr35 |= 0x60;
+                } else {
+                   cr30 |= 0x80;
+                }
                 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE;
-                cr31 |= 0x01;
-                cr35 |= 0x01;
+                cr31 |= 0x01;
+                cr35 |= 0x01;
                 ivideo->currentvbflags |= TV_HIVISION;
              } else if(ivideo->vbflags & TV_SCART) {
                 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
@@ -3466,8 +3713,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
              }
              cr31 |= SIS_DRIVER_MODE;
 
-             if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
-                if(ivideo->vbflags & TV_PAL) {
+             if(ivideo->vbflags & (TV_AVIDEO | TV_SVIDEO)) {
+                if(ivideo->vbflags & TV_PAL) {
                    cr31 |= 0x01; cr35 |= 0x01;
                    ivideo->currentvbflags |= TV_PAL;
                    if(ivideo->vbflags & TV_PALM) {
@@ -3476,14 +3723,14 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
                    } else if(ivideo->vbflags & TV_PALN) {
                       cr38 |= 0x80; cr35 |= 0x08;
                       ivideo->currentvbflags |= TV_PALN;
-                   }
-                 } else {
+                   }
+                } else {
                    cr31 &= ~0x01; cr35 &= ~0x01;
                    ivideo->currentvbflags |= TV_NTSC;
                    if(ivideo->vbflags & TV_NTSCJ) {
                       cr38 |= 0x40; cr35 |= 0x02;
                       ivideo->currentvbflags |= TV_NTSCJ;
-                   }
+                   }
                 }
              }
              break;
@@ -3493,6 +3740,8 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
              cr31 |= SIS_DRIVER_MODE;
              SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
              SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
+             ivideo->curFSTN = ivideo->sisfb_fstn;
+             ivideo->curDSTN = ivideo->sisfb_dstn;
              break;
 
           case CRT2_VGA:
@@ -3525,9 +3774,9 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
        }
        outSISIDXREG(SISCR, 0x31, cr31);
 
-       if(ivideo->accel) sisfb_syncaccel(ivideo);
-
        ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+
+       sisfb_check_engine_and_sync(ivideo);
 }
 
 /* Fix SR11 for 661 and later */
@@ -3535,125 +3784,129 @@ sisfb_pre_setmode(struct sis_video_info *ivideo)
 static void
 sisfb_fixup_SR11(struct sis_video_info *ivideo)
 {
-    u8  tmpreg;
-
-    if(ivideo->chip >= SIS_661) {
-       inSISIDXREG(SISSR,0x11,tmpreg);
-       if(tmpreg & 0x20) {
-          inSISIDXREG(SISSR,0x3e,tmpreg);
-         tmpreg = (tmpreg + 1) & 0xff;
-         outSISIDXREG(SISSR,0x3e,tmpreg);
-         inSISIDXREG(SISSR,0x11,tmpreg);
-       }
-       if(tmpreg & 0xf0) {
-          andSISIDXREG(SISSR,0x11,0x0f);
-       }
-    }
+       u8  tmpreg;
+
+       if(ivideo->chip >= SIS_661) {
+               inSISIDXREG(SISSR,0x11,tmpreg);
+               if(tmpreg & 0x20) {
+                       inSISIDXREG(SISSR,0x3e,tmpreg);
+                       tmpreg = (tmpreg + 1) & 0xff;
+                       outSISIDXREG(SISSR,0x3e,tmpreg);
+                       inSISIDXREG(SISSR,0x11,tmpreg);
+               }
+               if(tmpreg & 0xf0) {
+                       andSISIDXREG(SISSR,0x11,0x0f);
+               }
+       }
 }
 #endif
 
-static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+static void
+sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
 {
-   if(val > 32) val = 32;
-   if(val < -32) val = -32;
-   ivideo->tvxpos = val;
+       if(val > 32) val = 32;
+       if(val < -32) val = -32;
+       ivideo->tvxpos = val;
 
-   if(ivideo->sisfblocked) return;
-   if(!ivideo->modechanged) return;
+       if(ivideo->sisfblocked) return;
+       if(!ivideo->modechanged) return;
 
-   if(ivideo->currentvbflags & CRT2_TV) {
+       if(ivideo->currentvbflags & CRT2_TV) {
 
-      if(ivideo->vbflags & VB_CHRONTEL) {
+               if(ivideo->vbflags2 & VB2_CHRONTEL) {
 
-        int x = ivideo->tvx;
+                       int x = ivideo->tvx;
 
-        switch(ivideo->chronteltype) {
-        case 1:
-            x += val;
-            if(x < 0) x = 0;
-            outSISIDXREG(SISSR,0x05,0x86);
-            SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
-            SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
-            break;
-        case 2:
-            /* Not supported by hardware */
-            break;
-        }
-
-      } else if(ivideo->vbflags & VB_SISBRIDGE) {
-
-        u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
-        unsigned short temp;
-
-        p2_1f = ivideo->p2_1f;
-        p2_20 = ivideo->p2_20;
-        p2_2b = ivideo->p2_2b;
-        p2_42 = ivideo->p2_42;
-        p2_43 = ivideo->p2_43;
-
-        temp = p2_1f | ((p2_20 & 0xf0) << 4);
-        temp += (val * 2);
-        p2_1f = temp & 0xff;
-        p2_20 = (temp & 0xf00) >> 4;
-        p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
-        temp = p2_43 | ((p2_42 & 0xf0) << 4);
-        temp += (val * 2);
-        p2_43 = temp & 0xff;
-        p2_42 = (temp & 0xf00) >> 4;
-        outSISIDXREG(SISPART2,0x1f,p2_1f);
-        setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
-        setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
-        setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
-        outSISIDXREG(SISPART2,0x43,p2_43);
-      }
-   }
+                       switch(ivideo->chronteltype) {
+                       case 1:
+                               x += val;
+                               if(x < 0) x = 0;
+                               outSISIDXREG(SISSR,0x05,0x86);
+                               SiS_SetCH700x(&ivideo->SiS_Pr, 0x0a, (x & 0xff));
+                               SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((x & 0x0100) >> 7), 0xFD);
+                               break;
+                       case 2:
+                               /* Not supported by hardware */
+                               break;
+                       }
+
+               } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+                       u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+                       unsigned short temp;
+
+                       p2_1f = ivideo->p2_1f;
+                       p2_20 = ivideo->p2_20;
+                       p2_2b = ivideo->p2_2b;
+                       p2_42 = ivideo->p2_42;
+                       p2_43 = ivideo->p2_43;
+
+                       temp = p2_1f | ((p2_20 & 0xf0) << 4);
+                       temp += (val * 2);
+                       p2_1f = temp & 0xff;
+                       p2_20 = (temp & 0xf00) >> 4;
+                       p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+                       temp = p2_43 | ((p2_42 & 0xf0) << 4);
+                       temp += (val * 2);
+                       p2_43 = temp & 0xff;
+                       p2_42 = (temp & 0xf00) >> 4;
+                       outSISIDXREG(SISPART2,0x1f,p2_1f);
+                       setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
+                       setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
+                       setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
+                       outSISIDXREG(SISPART2,0x43,p2_43);
+               }
+       }
 }
 
-static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+static void
+sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
 {
-   if(val > 32) val = 32;
-   if(val < -32) val = -32;
-   ivideo->tvypos = val;
-
-   if(ivideo->sisfblocked) return;
-   if(!ivideo->modechanged) return;
-
-   if(ivideo->currentvbflags & CRT2_TV) {
-
-      if(ivideo->vbflags & VB_CHRONTEL) {
-
-        int y = ivideo->tvy;
-
-        switch(ivideo->chronteltype) {
-        case 1:
-           y -= val;
-           if(y < 0) y = 0;
-           outSISIDXREG(SISSR,0x05,0x86);
-           SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
-           SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
-           break;
-        case 2:
-           /* Not supported by hardware */
-           break;
-        }
-
-      } else if(ivideo->vbflags & VB_SISBRIDGE) {
-
-        char p2_01, p2_02;
-        val /= 2;
-        p2_01 = ivideo->p2_01;
-        p2_02 = ivideo->p2_02;
-
-        p2_01 += val;
-        p2_02 += val;
-        while((p2_01 <= 0) || (p2_02 <= 0)) {
-           p2_01 += 2;
-           p2_02 += 2;
-        }
-        outSISIDXREG(SISPART2,0x01,p2_01);
-        outSISIDXREG(SISPART2,0x02,p2_02);
-      }
-   }
+       if(val > 32) val = 32;
+       if(val < -32) val = -32;
+       ivideo->tvypos = val;
+
+       if(ivideo->sisfblocked) return;
+       if(!ivideo->modechanged) return;
+
+       if(ivideo->currentvbflags & CRT2_TV) {
+
+               if(ivideo->vbflags2 & VB2_CHRONTEL) {
+
+                       int y = ivideo->tvy;
+
+                       switch(ivideo->chronteltype) {
+                       case 1:
+                               y -= val;
+                               if(y < 0) y = 0;
+                               outSISIDXREG(SISSR,0x05,0x86);
+                               SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b, (y & 0xff));
+                               SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x08, ((y & 0x0100) >> 8), 0xFE);
+                               break;
+                       case 2:
+                               /* Not supported by hardware */
+                               break;
+                       }
+
+               } else if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+
+                       char p2_01, p2_02;
+                       val /= 2;
+                       p2_01 = ivideo->p2_01;
+                       p2_02 = ivideo->p2_02;
+
+                       p2_01 += val;
+                       p2_02 += val;
+                       if(!(ivideo->currentvbflags & (TV_HIVISION | TV_YPBPR))) {
+                               while((p2_01 <= 0) || (p2_02 <= 0)) {
+                                       p2_01 += 2;
+                                       p2_02 += 2;
+                               }
+                       }
+                       outSISIDXREG(SISPART2,0x01,p2_01);
+                       outSISIDXREG(SISPART2,0x02,p2_02);
+               }
+       }
 }
 
 static void
@@ -3668,207 +3921,172 @@ sisfb_post_setmode(struct sis_video_info *ivideo)
        u8 reg1;
 #endif
 
-       outSISIDXREG(SISSR,0x05,0x86);
+       outSISIDXREG(SISSR, 0x05, 0x86);
 
 #ifdef CONFIG_FB_SIS_315
        sisfb_fixup_SR11(ivideo);
 #endif
 
        /* Now we actually HAVE changed the display mode */
-        ivideo->modechanged = 1;
+       ivideo->modechanged = 1;
 
        /* We can't switch off CRT1 if bridge is in slave mode */
-       if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+       if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
                if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
-       } else ivideo->sisfb_crt1off = 0;
+       } else
+               ivideo->sisfb_crt1off = 0;
 
 #ifdef CONFIG_FB_SIS_300
        if(ivideo->sisvga_engine == SIS_300_VGA) {
-          if((ivideo->sisfb_crt1off) && (doit)) {
-               crt1isoff = TRUE;
-               reg = 0x00;
-          } else {
-               crt1isoff = FALSE;
-               reg = 0x80;
-          }
-          setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+               if((ivideo->sisfb_crt1off) && (doit)) {
+                       crt1isoff = TRUE;
+                       reg = 0x00;
+               } else {
+                       crt1isoff = FALSE;
+                       reg = 0x80;
+               }
+               setSISIDXREG(SISCR, 0x17, 0x7f, reg);
        }
 #endif
 #ifdef CONFIG_FB_SIS_315
        if(ivideo->sisvga_engine == SIS_315_VGA) {
-          if((ivideo->sisfb_crt1off) && (doit)) {
-               crt1isoff = TRUE;
-               reg  = 0x40;
-               reg1 = 0xc0;
-          } else {
-               crt1isoff = FALSE;
-               reg  = 0x00;
-               reg1 = 0x00;
-
-          }
-          setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
-          setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
+               if((ivideo->sisfb_crt1off) && (doit)) {
+                       crt1isoff = TRUE;
+                       reg  = 0x40;
+                       reg1 = 0xc0;
+               } else {
+                       crt1isoff = FALSE;
+                       reg  = 0x00;
+                       reg1 = 0x00;
+               }
+               setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
+               setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
        }
 #endif
 
        if(crt1isoff) {
-          ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
-          ivideo->currentvbflags |= VB_SINGLE_MODE;
+               ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+               ivideo->currentvbflags |= VB_SINGLE_MODE;
        } else {
-          ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
-          if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
-               ivideo->currentvbflags |= VB_MIRROR_MODE;
-          } else {
-               ivideo->currentvbflags |= VB_SINGLE_MODE;
-          }
+               ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+               if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+                       ivideo->currentvbflags |= VB_MIRROR_MODE;
+               } else {
+                       ivideo->currentvbflags |= VB_SINGLE_MODE;
+               }
        }
 
-        andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+       andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
 
        if(ivideo->currentvbflags & CRT2_TV) {
-          if(ivideo->vbflags & VB_SISBRIDGE) {
-             inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
-             inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
-             inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
-             inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
-             inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
-             inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
-             inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
-          } else if(ivideo->vbflags & VB_CHRONTEL) {
-             if(ivideo->chronteltype == 1) {
-                ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
-                ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
-                ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
-                ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
-             }
-          }
+               if(ivideo->vbflags2 & VB2_SISBRIDGE) {
+                       inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
+                       inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
+                       inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
+                       inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
+                       inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
+                       inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
+                       inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+               } else if(ivideo->vbflags2 & VB2_CHRONTEL) {
+                       if(ivideo->chronteltype == 1) {
+                               ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+                               ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+                               ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+                               ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+                       }
+               }
        }
 
        if(ivideo->tvxpos) {
-          sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+               sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
        }
        if(ivideo->tvypos) {
-          sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+               sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
        }
 
-       if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) {  /* Set filter for SiS301 */
+       /* Eventually sync engines */
+       sisfb_check_engine_and_sync(ivideo);
 
-               unsigned char filter_tb = 0;
+       /* (Re-)Initialize chip engines */
+       if(ivideo->accel) {
+               sisfb_engine_init(ivideo);
+       } else {
+               ivideo->engineok = 0;
+       }
+}
 
-               switch (ivideo->video_width) {
-                  case 320:
-                       filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
-                       break;
-                  case 640:
-                       filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
-                       break;
-                  case 720:
-                       filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
-                       break;
-                  case 400:
-                  case 800:
-                       filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
-                       break;
-                  default:
-                       ivideo->sisfb_filter = -1;
-                       break;
-               }
+static int
+sisfb_reset_mode(struct sis_video_info *ivideo)
+{
+       if(sisfb_set_mode(ivideo, 0))
+               return 1;
 
-               orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
+       sisfb_set_pitch(ivideo);
+       sisfb_set_base_CRT1(ivideo, ivideo->current_base);
+       sisfb_set_base_CRT2(ivideo, ivideo->current_base);
 
-               if(ivideo->vbflags & TV_NTSC) {
-
-                       andSISIDXREG(SISPART2, 0x3a, 0x1f);
-
-                       if (ivideo->vbflags & TV_SVIDEO) {
-
-                               andSISIDXREG(SISPART2, 0x30, 0xdf);
-
-                       } else if (ivideo->vbflags & TV_AVIDEO) {
-
-                               orSISIDXREG(SISPART2, 0x30, 0x20);
-
-                               switch (ivideo->video_width) {
-                               case 640:
-                                       outSISIDXREG(SISPART2, 0x35, 0xEB);
-                                       outSISIDXREG(SISPART2, 0x36, 0x04);
-                                       outSISIDXREG(SISPART2, 0x37, 0x25);
-                                       outSISIDXREG(SISPART2, 0x38, 0x18);
-                                       break;
-                               case 720:
-                                       outSISIDXREG(SISPART2, 0x35, 0xEE);
-                                       outSISIDXREG(SISPART2, 0x36, 0x0C);
-                                       outSISIDXREG(SISPART2, 0x37, 0x22);
-                                       outSISIDXREG(SISPART2, 0x38, 0x08);
-                                       break;
-                               case 400:
-                               case 800:
-                                       outSISIDXREG(SISPART2, 0x35, 0xEB);
-                                       outSISIDXREG(SISPART2, 0x36, 0x15);
-                                       outSISIDXREG(SISPART2, 0x37, 0x25);
-                                       outSISIDXREG(SISPART2, 0x38, 0xF6);
-                                       break;
-                               }
-                       }
+       return 0;
+}
+
+static void
+sisfb_handle_command(struct sis_video_info *ivideo, struct sisfb_cmd *sisfb_command)
+{
+       int mycrt1off;
 
-               } else if(ivideo->vbflags & TV_PAL) {
-
-                       andSISIDXREG(SISPART2, 0x3A, 0x1F);
-
-                       if (ivideo->vbflags & TV_SVIDEO) {
-
-                               andSISIDXREG(SISPART2, 0x30, 0xDF);
-
-                       } else if (ivideo->vbflags & TV_AVIDEO) {
-
-                               orSISIDXREG(SISPART2, 0x30, 0x20);
-
-                               switch (ivideo->video_width) {
-                               case 640:
-                                       outSISIDXREG(SISPART2, 0x35, 0xF1);
-                                       outSISIDXREG(SISPART2, 0x36, 0xF7);
-                                       outSISIDXREG(SISPART2, 0x37, 0x1F);
-                                       outSISIDXREG(SISPART2, 0x38, 0x32);
-                                       break;
-                               case 720:
-                                       outSISIDXREG(SISPART2, 0x35, 0xF3);
-                                       outSISIDXREG(SISPART2, 0x36, 0x00);
-                                       outSISIDXREG(SISPART2, 0x37, 0x1D);
-                                       outSISIDXREG(SISPART2, 0x38, 0x20);
-                                       break;
-                               case 400:
-                               case 800:
-                                       outSISIDXREG(SISPART2, 0x35, 0xFC);
-                                       outSISIDXREG(SISPART2, 0x36, 0xFB);
-                                       outSISIDXREG(SISPART2, 0x37, 0x14);
-                                       outSISIDXREG(SISPART2, 0x38, 0x2A);
-                                       break;
+       switch(sisfb_command->sisfb_cmd) {
+       case SISFB_CMD_GETVBFLAGS:
+               if(!ivideo->modechanged) {
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+               } else {
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+                       sisfb_command->sisfb_result[1] = ivideo->currentvbflags;
+                       sisfb_command->sisfb_result[2] = ivideo->vbflags2;
+               }
+               break;
+       case SISFB_CMD_SWITCHCRT1:
+               /* arg[0]: 0 = off, 1 = on, 99 = query */
+               if(!ivideo->modechanged) {
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_EARLY;
+               } else if(sisfb_command->sisfb_arg[0] == 99) {
+                       /* Query */
+                       sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+               } else if(ivideo->sisfblocked) {
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_LOCKED;
+               } else if((!(ivideo->currentvbflags & CRT2_ENABLE)) &&
+                                       (sisfb_command->sisfb_arg[0] == 0)) {
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_NOCRT2;
+               } else {
+                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OK;
+                       mycrt1off = sisfb_command->sisfb_arg[0] ? 0 : 1;
+                       if( ((ivideo->currentvbflags & VB_DISPTYPE_CRT1) && mycrt1off) ||
+                           ((!(ivideo->currentvbflags & VB_DISPTYPE_CRT1)) && !mycrt1off) ) {
+                               ivideo->sisfb_crt1off = mycrt1off;
+                               if(sisfb_reset_mode(ivideo)) {
+                                       sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_OTHER;
                                }
                        }
+                       sisfb_command->sisfb_result[1] = ivideo->sisfb_crt1off ? 0 : 1;
                }
-
-               if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
-                  outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
-                  outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
-                  outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
-                  outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
-               }
-         
+               break;
+       /* more to come */
+       default:
+               sisfb_command->sisfb_result[0] = SISFB_CMD_ERR_UNKNOWN;
+               printk(KERN_ERR "sisfb: Unknown command 0x%x\n",
+                       sisfb_command->sisfb_cmd);
        }
 }
 
 #ifndef MODULE
-SISINITSTATIC int __init sisfb_setup(char *options)
+SISINITSTATIC int __init
+sisfb_setup(char *options)
 {
        char *this_opt;
-       
-       sisfb_setdefaultparms();
 
-        printk(KERN_DEBUG "sisfb: Options %s\n", options);
+       sisfb_setdefaultparms();
 
-       if(!options || !(*options)) {
+       if(!options || !(*options))
                return 0;
-       }
 
        while((this_opt = strsep(&options, ",")) != NULL) {
 
@@ -3880,9 +4098,9 @@ SISINITSTATIC int __init sisfb_setup(char *options)
                        /* Need to check crt2 type first for fstn/dstn */
                        sisfb_search_crt2type(this_opt + 14);
                } else if(!strnicmp(this_opt, "tvmode:",7)) {
-                       sisfb_search_tvstd(this_opt + 7);
-                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
                        sisfb_search_tvstd(this_opt + 7);
+               } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+                       sisfb_search_tvstd(this_opt + 11);
                } else if(!strnicmp(this_opt, "mode:", 5)) {
                        sisfb_search_mode(this_opt + 5, FALSE);
                } else if(!strnicmp(this_opt, "vesa:", 5)) {
@@ -3892,74 +4110,72 @@ SISINITSTATIC int __init sisfb_setup(char *options)
                        sisfb_inverse = 1;
                        /* fb_invert_cmaps(); */
                } else if(!strnicmp(this_opt, "font:", 5)) {
-                       if(strlen(this_opt + 5) < 40) {
+                       if(strlen(this_opt + 5) < 40) {
                           strncpy(sisfb_fontname, this_opt + 5, sizeof(sisfb_fontname) - 1);
                           sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
                        }
 #endif
                } else if(!strnicmp(this_opt, "rate:", 5)) {
                        sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
-               } else if(!strnicmp(this_opt, "filter:", 7)) {
-                       sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
                } else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
                        sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-                } else if(!strnicmp(this_opt, "mem:",4)) {
-                       sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
+               } else if(!strnicmp(this_opt, "mem:",4)) {
+                       sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
                } else if(!strnicmp(this_opt, "pdc:", 4)) {
-                       sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
+                       sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
                } else if(!strnicmp(this_opt, "pdc1:", 5)) {
-                       sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
+                       sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
                } else if(!strnicmp(this_opt, "noaccel", 7)) {
                        sisfb_accel = 0;
                } else if(!strnicmp(this_opt, "accel", 5)) {
                        sisfb_accel = -1;
                } else if(!strnicmp(this_opt, "noypan", 6)) {
-                       sisfb_ypan = 0;
+                       sisfb_ypan = 0;
                } else if(!strnicmp(this_opt, "ypan", 4)) {
-                       sisfb_ypan = -1;
+                       sisfb_ypan = -1;
                } else if(!strnicmp(this_opt, "nomax", 5)) {
-                       sisfb_max = 0;
+                       sisfb_max = 0;
                } else if(!strnicmp(this_opt, "max", 3)) {
-                       sisfb_max = -1;
+                       sisfb_max = -1;
                } else if(!strnicmp(this_opt, "userom:", 7)) {
                        sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
                } else if(!strnicmp(this_opt, "useoem:", 7)) {
                        sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
                } else if(!strnicmp(this_opt, "nocrt2rate", 10)) {
                        sisfb_nocrt2rate = 1;
-               } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
-                       unsigned long temp = 2;
-                       temp = simple_strtoul(this_opt + 9, NULL, 0);
-                       if((temp == 0) || (temp == 1)) {
+               } else if(!strnicmp(this_opt, "scalelcd:", 9)) {
+                       unsigned long temp = 2;
+                       temp = simple_strtoul(this_opt + 9, NULL, 0);
+                       if((temp == 0) || (temp == 1)) {
                           sisfb_scalelcd = temp ^ 1;
-                       }
+                       }
                } else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
-                       int temp = 0;
-                       temp = (int)simple_strtol(this_opt + 13, NULL, 0);
-                       if((temp >= -32) && (temp <= 32)) {
+                       int temp = 0;
+                       temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+                       if((temp >= -32) && (temp <= 32)) {
                           sisfb_tvxposoffset = temp;
-                       }
+                       }
                } else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
-                       int temp = 0;
-                       temp = (int)simple_strtol(this_opt + 13, NULL, 0);
-                       if((temp >= -32) && (temp <= 32)) {
+                       int temp = 0;
+                       temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+                       if((temp >= -32) && (temp <= 32)) {
                           sisfb_tvyposoffset = temp;
-                       }
+                       }
                } else if(!strnicmp(this_opt, "specialtiming:", 14)) {
                        sisfb_search_specialtiming(this_opt + 14);
                } else if(!strnicmp(this_opt, "lvdshl:", 7)) {
-                       int temp = 4;
-                       temp = simple_strtoul(this_opt + 7, NULL, 0);
-                       if((temp >= 0) && (temp <= 3)) {
+                       int temp = 4;
+                       temp = simple_strtoul(this_opt + 7, NULL, 0);
+                       if((temp >= 0) && (temp <= 3)) {
                           sisfb_lvdshl = temp;
-                       }
+                       }
                } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
                        sisfb_search_mode(this_opt, TRUE);
 #if !defined(__i386__) && !defined(__x86_64__)
-               } else if(!strnicmp(this_opt, "resetcard", 9)) {
-                       sisfb_resetcard = 1;
+               } else if(!strnicmp(this_opt, "resetcard", 9)) {
+                       sisfb_resetcard = 1;
                } else if(!strnicmp(this_opt, "videoram:", 9)) {
-                       sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
+                       sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
 #endif
                } else {
                        printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
@@ -3967,819 +4183,1706 @@ SISINITSTATIC int __init sisfb_setup(char *options)
 
        }
 
+       return 0;
+}
+#endif
+
+static int __devinit
+sisfb_check_rom(SIS_IOTYPE1 *rom_base, struct sis_video_info *ivideo)
+{
+       SIS_IOTYPE1 *rom;
+       int romptr;
+
+       if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa))
+               return 0;
+
+       romptr = (readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+       if(romptr > (0x10000 - 8))
+               return 0;
+
+       rom = rom_base + romptr;
+
+       if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+          (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R'))
+               return 0;
+
+       if((readb(rom + 4) | (readb(rom + 5) << 8)) != ivideo->chip_vendor)
+               return 0;
+
+       if((readb(rom + 6) | (readb(rom + 7) << 8)) != ivideo->chip_id)
+               return 0;
+
+       return 1;
+}
+
+static unsigned char * __devinit
+sisfb_find_rom(struct pci_dev *pdev)
+{
+       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+       SIS_IOTYPE1 *rom_base;
+       unsigned char *myrombase = NULL;
+       u32 temp;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
+       size_t romsize;
+
+       /* First, try the official pci ROM functions (except
+        * on integrated chipsets which have no ROM).
+        */
+
+       if(!ivideo->nbridge) {
+
+               if((rom_base = pci_map_rom(pdev, &romsize))) {
+
+                       if(sisfb_check_rom(rom_base, ivideo)) {
+
+                               if((myrombase = vmalloc(65536))) {
+
+                                       /* Work around bug in pci/rom.c: Folks forgot to check
+                                        * whether the size retrieved from the BIOS image eventually
+                                        * is larger than the mapped size
+                                        */
+                                       if(pci_resource_len(pdev, PCI_ROM_RESOURCE) < romsize)
+                                               romsize = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+
+                                       memcpy_fromio(myrombase, rom_base,
+                                                       (romsize > 65536) ? 65536 : romsize);
+                               }
+                       }
+                       pci_unmap_rom(pdev, rom_base);
+               }
+       }
+
+       if(myrombase) return myrombase;
+#endif
+
+       /* Otherwise do it the conventional way. */
+
+#if defined(__i386__) || defined(__x86_64__)
+
+       for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+
+               rom_base = ioremap(temp, 65536);
+               if(!rom_base)
+                       continue;
+
+               if(!sisfb_check_rom(rom_base, ivideo)) {
+                       iounmap(rom_base);
+                       continue;
+               }
+
+               if((myrombase = vmalloc(65536)))
+                       memcpy_fromio(myrombase, rom_base, 65536);
+
+               iounmap(rom_base);
+               break;
+
+        }
+
+#else
+
+       pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+                       (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+
+       rom_base = ioremap(ivideo->video_base, 65536);
+       if(rom_base) {
+               if(sisfb_check_rom(rom_base, ivideo)) {
+                       if((myrombase = vmalloc(65536)))
+                               memcpy_fromio(myrombase, rom_base, 65536);
+               }
+               iounmap(rom_base);
+       }
+
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
+
+#endif
+
+       return myrombase;
+}
+
+static void __devinit
+sisfb_post_map_vram(struct sis_video_info *ivideo, unsigned int *mapsize,
+                       unsigned int min)
+{
+       ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize));
+
+       if(!ivideo->video_vbase) {
+               printk(KERN_ERR
+                       "sisfb: Unable to map maximum video RAM for size detection\n");
+               (*mapsize) >>= 1;
+               while((!(ivideo->video_vbase = ioremap(ivideo->video_base, (*mapsize))))) {
+                       (*mapsize) >>= 1;
+                       if((*mapsize) < (min << 20))
+                               break;
+               }
+               if(ivideo->video_vbase) {
+                       printk(KERN_ERR
+                               "sisfb: Video RAM size detection limited to %dMB\n",
+                               (int)((*mapsize) >> 20));
+               }
+       }
+}
+
+#ifdef CONFIG_FB_SIS_300
+static int __devinit
+sisfb_post_300_buswidth(struct sis_video_info *ivideo)
+{
+       SIS_IOTYPE1 *FBAddress = ivideo->video_vbase;
+       unsigned short temp;
+       unsigned char reg;
+       int i, j;
+
+       andSISIDXREG(SISSR, 0x15, 0xFB);
+       orSISIDXREG(SISSR, 0x15, 0x04);
+       outSISIDXREG(SISSR, 0x13, 0x00);
+       outSISIDXREG(SISSR, 0x14, 0xBF);
+
+       for(i = 0; i < 2; i++) {
+               temp = 0x1234;
+               for(j = 0; j < 4; j++) {
+                       writew(temp, FBAddress);
+                       if(readw(FBAddress) == temp)
+                               break;
+                       orSISIDXREG(SISSR, 0x3c, 0x01);
+                       inSISIDXREG(SISSR, 0x05, reg);
+                       inSISIDXREG(SISSR, 0x05, reg);
+                       andSISIDXREG(SISSR, 0x3c, 0xfe);
+                       inSISIDXREG(SISSR, 0x05, reg);
+                       inSISIDXREG(SISSR, 0x05, reg);
+                       temp++;
+               }
+       }
+
+       writel(0x01234567L, FBAddress);
+       writel(0x456789ABL, (FBAddress + 4));
+       writel(0x89ABCDEFL, (FBAddress + 8));
+       writel(0xCDEF0123L, (FBAddress + 12));
+
+       inSISIDXREG(SISSR, 0x3b, reg);
+       if(reg & 0x01) {
+               if(readl((FBAddress + 12)) == 0xCDEF0123L)
+                       return 4;       /* Channel A 128bit */
+       }
+
+       if(readl((FBAddress + 4)) == 0x456789ABL)
+               return 2;               /* Channel B 64bit */
+
+       return 1;                       /* 32bit */
+}
+
+static int __devinit
+sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
+                       int PseudoRankCapacity, int PseudoAdrPinCount,
+                       unsigned int mapsize)
+{
+       SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
+       unsigned short sr14;
+       unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
+       unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
+       static const unsigned short SiS_DRAMType[17][5] = {
+               {0x0C,0x0A,0x02,0x40,0x39},
+               {0x0D,0x0A,0x01,0x40,0x48},
+               {0x0C,0x09,0x02,0x20,0x35},
+               {0x0D,0x09,0x01,0x20,0x44},
+               {0x0C,0x08,0x02,0x10,0x31},
+               {0x0D,0x08,0x01,0x10,0x40},
+               {0x0C,0x0A,0x01,0x20,0x34},
+               {0x0C,0x09,0x01,0x08,0x32},
+               {0x0B,0x08,0x02,0x08,0x21},
+               {0x0C,0x08,0x01,0x08,0x30},
+               {0x0A,0x08,0x02,0x04,0x11},
+               {0x0B,0x0A,0x01,0x10,0x28},
+               {0x09,0x08,0x02,0x02,0x01},
+               {0x0B,0x09,0x01,0x08,0x24},
+               {0x0B,0x08,0x01,0x04,0x20},
+               {0x0A,0x08,0x01,0x02,0x10},
+               {0x09,0x08,0x01,0x01,0x00}
+       };
+
+        for(k = 0; k <= 16; k++) {
+
+               RankCapacity = buswidth * SiS_DRAMType[k][3];
+
+               if(RankCapacity != PseudoRankCapacity)
+                       continue;
+
+               if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
+                       continue;
+
+               BankNumHigh = RankCapacity * 16 * iteration - 1;
+               if(iteration == 3) {             /* Rank No */
+                       BankNumMid  = RankCapacity * 16 - 1;
+               } else {
+                       BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
+               }
+
+               PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
+               PhysicalAdrHigh = BankNumHigh;
+               PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
+               PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
+
+               andSISIDXREG(SISSR, 0x15, 0xFB); /* Test */
+               orSISIDXREG(SISSR, 0x15, 0x04);  /* Test */
+               sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
+               if(buswidth == 4)      sr14 |= 0x80;
+               else if(buswidth == 2) sr14 |= 0x40;
+               outSISIDXREG(SISSR, 0x13, SiS_DRAMType[k][4]);
+               outSISIDXREG(SISSR, 0x14, sr14);
+
+               BankNumHigh <<= 16;
+               BankNumMid <<= 16;
+
+               if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
+                  (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
+                  (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
+                  (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
+                       continue;
+
+               /* Write data */
+               writew(((unsigned short)PhysicalAdrHigh),
+                               (FBAddr + BankNumHigh + PhysicalAdrHigh));
+               writew(((unsigned short)BankNumMid),
+                               (FBAddr + BankNumMid  + PhysicalAdrHigh));
+               writew(((unsigned short)PhysicalAdrHalfPage),
+                               (FBAddr + BankNumHigh + PhysicalAdrHalfPage));
+               writew(((unsigned short)PhysicalAdrOtherPage),
+                               (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
+
+               /* Read data */
+               if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static void __devinit
+sisfb_post_300_ramsize(struct pci_dev *pdev, unsigned int mapsize)
+{
+       struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
+       int     i, j, buswidth;
+       int     PseudoRankCapacity, PseudoAdrPinCount;
+
+       buswidth = sisfb_post_300_buswidth(ivideo);
+
+       for(i = 6; i >= 0; i--) {
+               PseudoRankCapacity = 1 << i;
+               for(j = 4; j >= 1; j--) {
+                       PseudoAdrPinCount = 15 - j;
+                       if((PseudoRankCapacity * j) <= 64) {
+                               if(sisfb_post_300_rwtest(ivideo,
+                                               j,
+                                               buswidth,
+                                               PseudoRankCapacity,
+                                               PseudoAdrPinCount,
+                                               mapsize))
+                                       return;
+                       }
+               }
+       }
+}
+
+static void __devinit
+sisfb_post_sis300(struct pci_dev *pdev)
+{
+       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+       unsigned char *bios = ivideo->SiS_Pr.VirtualRomBase;
+       u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
+       u16 index, rindex, memtype = 0;
+       unsigned int mapsize;
+
+       if(!ivideo->SiS_Pr.UseROM)
+               bios = NULL;
+
+       outSISIDXREG(SISSR, 0x05, 0x86);
+
+       if(bios) {
+               if(bios[0x52] & 0x80) {
+                       memtype = bios[0x52];
+               } else {
+                       inSISIDXREG(SISSR, 0x3a, memtype);
+               }
+               memtype &= 0x07;
+       }
+
+       v3 = 0x80; v6 = 0x80;
+       if(ivideo->revision_id <= 0x13) {
+               v1 = 0x44; v2 = 0x42;
+               v4 = 0x44; v5 = 0x42;
+       } else {
+               v1 = 0x68; v2 = 0x43; /* Assume 125Mhz MCLK */
+               v4 = 0x68; v5 = 0x43; /* Assume 125Mhz ECLK */
+               if(bios) {
+                       index = memtype * 5;
+                       rindex = index + 0x54;
+                       v1 = bios[rindex++];
+                       v2 = bios[rindex++];
+                       v3 = bios[rindex++];
+                       rindex = index + 0x7c;
+                       v4 = bios[rindex++];
+                       v5 = bios[rindex++];
+                       v6 = bios[rindex++];
+               }
+       }
+       outSISIDXREG(SISSR, 0x28, v1);
+       outSISIDXREG(SISSR, 0x29, v2);
+       outSISIDXREG(SISSR, 0x2a, v3);
+       outSISIDXREG(SISSR, 0x2e, v4);
+       outSISIDXREG(SISSR, 0x2f, v5);
+       outSISIDXREG(SISSR, 0x30, v6);
+
+       v1 = 0x10;
+       if(bios)
+               v1 = bios[0xa4];
+       outSISIDXREG(SISSR, 0x07, v1);       /* DAC speed */
+
+       outSISIDXREG(SISSR, 0x11, 0x0f);     /* DDC, power save */
+
+       v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
+       v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
+       if(bios) {
+               memtype += 0xa5;
+               v1 = bios[memtype];
+               v2 = bios[memtype + 8];
+               v3 = bios[memtype + 16];
+               v4 = bios[memtype + 24];
+               v5 = bios[memtype + 32];
+               v6 = bios[memtype + 40];
+               v7 = bios[memtype + 48];
+               v8 = bios[memtype + 56];
+       }
+       if(ivideo->revision_id >= 0x80)
+               v3 &= 0xfd;
+       outSISIDXREG(SISSR, 0x15, v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
+       outSISIDXREG(SISSR, 0x16, v2);
+       outSISIDXREG(SISSR, 0x17, v3);
+       outSISIDXREG(SISSR, 0x18, v4);
+       outSISIDXREG(SISSR, 0x19, v5);
+       outSISIDXREG(SISSR, 0x1a, v6);
+       outSISIDXREG(SISSR, 0x1b, v7);
+       outSISIDXREG(SISSR, 0x1c, v8);     /* ---- */
+       andSISIDXREG(SISSR, 0x15 ,0xfb);
+       orSISIDXREG(SISSR, 0x15, 0x04);
+       if(bios) {
+               if(bios[0x53] & 0x02) {
+                       orSISIDXREG(SISSR, 0x19, 0x20);
+               }
+       }
+       v1 = 0x04;                         /* DAC pedestal (BIOS 0xe5) */
+       if(ivideo->revision_id >= 0x80)
+               v1 |= 0x01;
+       outSISIDXREG(SISSR, 0x1f, v1);
+       outSISIDXREG(SISSR, 0x20, 0xa4);     /* linear & relocated io & disable a0000 */
+       v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
+       if(bios) {
+               v1 = bios[0xe8];
+               v2 = bios[0xe9];
+               v3 = bios[0xea];
+       }
+       outSISIDXREG(SISSR, 0x23, v1);
+       outSISIDXREG(SISSR, 0x24, v2);
+       outSISIDXREG(SISSR, 0x25, v3);
+       outSISIDXREG(SISSR, 0x21, 0x84);
+       outSISIDXREG(SISSR, 0x22, 0x00);
+       outSISIDXREG(SISCR, 0x37, 0x00);
+       orSISIDXREG(SISPART1, 0x24, 0x01);   /* unlock crt2 */
+       outSISIDXREG(SISPART1, 0x00, 0x00);
+       v1 = 0x40; v2 = 0x11;
+       if(bios) {
+               v1 = bios[0xec];
+               v2 = bios[0xeb];
+       }
+       outSISIDXREG(SISPART1, 0x02, v1);
+
+       if(ivideo->revision_id >= 0x80)
+               v2 &= ~0x01;
+
+       inSISIDXREG(SISPART4, 0x00, reg);
+       if((reg == 1) || (reg == 2)) {
+               outSISIDXREG(SISCR, 0x37, 0x02);
+               outSISIDXREG(SISPART2, 0x00, 0x1c);
+               v4 = 0x00; v5 = 0x00; v6 = 0x10;
+               if(ivideo->SiS_Pr.UseROM) {
+                       v4 = bios[0xf5];
+                       v5 = bios[0xf6];
+                       v6 = bios[0xf7];
+               }
+               outSISIDXREG(SISPART4, 0x0d, v4);
+               outSISIDXREG(SISPART4, 0x0e, v5);
+               outSISIDXREG(SISPART4, 0x10, v6);
+               outSISIDXREG(SISPART4, 0x0f, 0x3f);
+               inSISIDXREG(SISPART4, 0x01, reg);
+               if(reg >= 0xb0) {
+                       inSISIDXREG(SISPART4, 0x23, reg);
+                       reg &= 0x20;
+                       reg <<= 1;
+                       outSISIDXREG(SISPART4, 0x23, reg);
+               }
+       } else {
+               v2 &= ~0x10;
+       }
+       outSISIDXREG(SISSR, 0x32, v2);
+
+       andSISIDXREG(SISPART1, 0x24, 0xfe);  /* Lock CRT2 */
+
+       inSISIDXREG(SISSR, 0x16, reg);
+       reg &= 0xc3;
+       outSISIDXREG(SISCR, 0x35, reg);
+       outSISIDXREG(SISCR, 0x83, 0x00);
+#if !defined(__i386__) && !defined(__x86_64__)
+       if(sisfb_videoram) {
+               outSISIDXREG(SISSR, 0x13, 0x28);  /* ? */
+               reg = ((sisfb_videoram >> 10) - 1) | 0x40;
+               outSISIDXREG(SISSR, 0x14, reg);
+       } else {
+#endif
+               /* Need to map max FB size for finding out about RAM size */
+               mapsize = 64 << 20;
+               sisfb_post_map_vram(ivideo, &mapsize, 4);
+
+               if(ivideo->video_vbase) {
+                       sisfb_post_300_ramsize(pdev, mapsize);
+                       iounmap(ivideo->video_vbase);
+               } else {
+                       printk(KERN_DEBUG
+                               "sisfb: Failed to map memory for size detection, assuming 8MB\n");
+                       outSISIDXREG(SISSR, 0x13, 0x28);  /* ? */
+                       outSISIDXREG(SISSR, 0x14, 0x47);  /* 8MB, 64bit default */
+               }
+#if !defined(__i386__) && !defined(__x86_64__)
+       }
+#endif
+       if(bios) {
+               v1 = bios[0xe6];
+               v2 = bios[0xe7];
+       } else {
+               inSISIDXREG(SISSR, 0x3a, reg);
+               if((reg & 0x30) == 0x30) {
+                       v1 = 0x04; /* PCI */
+                       v2 = 0x92;
+               } else {
+                       v1 = 0x14; /* AGP */
+                       v2 = 0xb2;
+               }
+       }
+       outSISIDXREG(SISSR, 0x21, v1);
+       outSISIDXREG(SISSR, 0x22, v2);
+
+       /* Sense CRT1 */
+       sisfb_sense_crt1(ivideo);
+
+       /* Set default mode, don't clear screen */
+       ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+       SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+       SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+       ivideo->curFSTN = ivideo->curDSTN = 0;
+       ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+       SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+       outSISIDXREG(SISSR, 0x05, 0x86);
+
+       /* Display off */
+       orSISIDXREG(SISSR, 0x01, 0x20);
+
+       /* Save mode number in CR34 */
+       outSISIDXREG(SISCR, 0x34, 0x2e);
+
+       /* Let everyone know what the current mode is */
+       ivideo->modeprechange = 0x2e;
+}
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+#if 0
+static void __devinit
+sisfb_post_sis315330(struct pci_dev *pdev)
+{
+       /* TODO */
+}
+#endif
+
+static void __devinit
+sisfb_post_xgi_delay(struct sis_video_info *ivideo, int delay)
+{
+       unsigned int i;
+       u8 reg;
+
+       for(i = 0; i <= (delay * 10 * 36); i++) {
+               inSISIDXREG(SISSR, 0x05, reg);
+               reg++;
+       }
+}
+
+static int __devinit
+sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev,
+                               unsigned short pcivendor)
+{
+       struct pci_dev *pdev = NULL;
+       unsigned short temp;
+       int ret = 0;
+
+       while((pdev = SIS_PCI_GET_CLASS(PCI_CLASS_BRIDGE_HOST, pdev))) {
+               temp = pdev->vendor;
+               SIS_PCI_PUT_DEVICE(pdev);
+               if(temp == pcivendor) {
+                       ret = 1;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int __devinit
+sisfb_post_xgi_rwtest(struct sis_video_info *ivideo, int starta,
+                       unsigned int enda, unsigned int mapsize)
+{
+       unsigned int pos;
+       int i;
+
+       writel(0, ivideo->video_vbase);
+
+       for(i = starta; i <= enda; i++) {
+               pos = 1 << i;
+               if(pos < mapsize)
+                       writel(pos, ivideo->video_vbase + pos);
+       }
+
+       sisfb_post_xgi_delay(ivideo, 150);
+
+       if(readl(ivideo->video_vbase) != 0)
+               return 0;
+
+       for(i = starta; i <= enda; i++) {
+               pos = 1 << i;
+               if(pos < mapsize) {
+                       if(readl(ivideo->video_vbase + pos) != pos)
+                               return 0;
+               } else
+                       return 0;
+       }
+
+       return 1;
+}
+
+static void __devinit
+sisfb_post_xgi_ramsize(struct sis_video_info *ivideo)
+{
+       unsigned int buswidth, ranksize, channelab, mapsize;
+       int i, j, k, l;
+       u8 reg, sr14;
+       static const u8 dramsr13[12 * 5] = {
+               0x02, 0x0e, 0x0b, 0x80, 0x5d,
+               0x02, 0x0e, 0x0a, 0x40, 0x59,
+               0x02, 0x0d, 0x0b, 0x40, 0x4d,
+               0x02, 0x0e, 0x09, 0x20, 0x55,
+               0x02, 0x0d, 0x0a, 0x20, 0x49,
+               0x02, 0x0c, 0x0b, 0x20, 0x3d,
+               0x02, 0x0e, 0x08, 0x10, 0x51,
+               0x02, 0x0d, 0x09, 0x10, 0x45,
+               0x02, 0x0c, 0x0a, 0x10, 0x39,
+               0x02, 0x0d, 0x08, 0x08, 0x41,
+               0x02, 0x0c, 0x09, 0x08, 0x35,
+               0x02, 0x0c, 0x08, 0x04, 0x31
+       };
+       static const u8 dramsr13_4[4 * 5] = {
+               0x02, 0x0d, 0x09, 0x40, 0x45,
+               0x02, 0x0c, 0x09, 0x20, 0x35,
+               0x02, 0x0c, 0x08, 0x10, 0x31,
+               0x02, 0x0b, 0x08, 0x08, 0x21
+       };
+
+       /* Enable linear mode, disable 0xa0000 address decoding */
+       /* We disable a0000 address decoding, because
+        * - if running on x86, if the card is disabled, it means
+        *   that another card is in the system. We don't want
+        *   to interphere with that primary card's textmode.
+        * - if running on non-x86, there usually is no VGA window
+        *   at a0000.
+        */
+       orSISIDXREG(SISSR, 0x20, (0x80 | 0x04));
+
+       /* Need to map max FB size for finding out about RAM size */
+       mapsize = 256 << 20;
+       sisfb_post_map_vram(ivideo, &mapsize, 32);
+
+       if(!ivideo->video_vbase) {
+               printk(KERN_ERR "sisfb: Unable to detect RAM size. Setting default.\n");
+               outSISIDXREG(SISSR, 0x13, 0x35);
+               outSISIDXREG(SISSR, 0x14, 0x41);
+               /* TODO */
+               return;
+       }
+
+       /* Non-interleaving */
+       outSISIDXREG(SISSR, 0x15, 0x00);
+       /* No tiling */
+       outSISIDXREG(SISSR, 0x1c, 0x00);
+
+       if(ivideo->chip == XGI_20) {
+
+               channelab = 1;
+               inSISIDXREG(SISCR, 0x97, reg);
+               if(!(reg & 0x01)) {     /* Single 32/16 */
+                       buswidth = 32;
+                       outSISIDXREG(SISSR, 0x13, 0xb1);
+                       outSISIDXREG(SISSR, 0x14, 0x52);
+                       sisfb_post_xgi_delay(ivideo, 1);
+                       sr14 = 0x02;
+                       if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+                               goto bail_out;
+
+                       outSISIDXREG(SISSR, 0x13, 0x31);
+                       outSISIDXREG(SISSR, 0x14, 0x42);
+                       sisfb_post_xgi_delay(ivideo, 1);
+                       if(sisfb_post_xgi_rwtest(ivideo, 23, 23, mapsize))
+                               goto bail_out;
+
+                       buswidth = 16;
+                       outSISIDXREG(SISSR, 0x13, 0xb1);
+                       outSISIDXREG(SISSR, 0x14, 0x41);
+                       sisfb_post_xgi_delay(ivideo, 1);
+                       sr14 = 0x01;
+                       if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+                               goto bail_out;
+                       else
+                               outSISIDXREG(SISSR, 0x13, 0x31);
+               } else {                /* Dual 16/8 */
+                       buswidth = 16;
+                       outSISIDXREG(SISSR, 0x13, 0xb1);
+                       outSISIDXREG(SISSR, 0x14, 0x41);
+                       sisfb_post_xgi_delay(ivideo, 1);
+                       sr14 = 0x01;
+                       if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+                               goto bail_out;
+
+                       outSISIDXREG(SISSR, 0x13, 0x31);
+                       outSISIDXREG(SISSR, 0x14, 0x31);
+                       sisfb_post_xgi_delay(ivideo, 1);
+                       if(sisfb_post_xgi_rwtest(ivideo, 22, 22, mapsize))
+                               goto bail_out;
+
+                       buswidth = 8;
+                       outSISIDXREG(SISSR, 0x13, 0xb1);
+                       outSISIDXREG(SISSR, 0x14, 0x30);
+                       sisfb_post_xgi_delay(ivideo, 1);
+                       sr14 = 0x00;
+                       if(sisfb_post_xgi_rwtest(ivideo, 21, 22, mapsize))
+                               goto bail_out;
+                       else
+                               outSISIDXREG(SISSR, 0x13, 0x31);
+               }
+
+       } else {        /* XGI_40 */
+
+               inSISIDXREG(SISCR, 0x97, reg);
+               if(!(reg & 0x10)) {
+                       inSISIDXREG(SISSR, 0x39, reg);
+                       reg >>= 1;
+               }
+
+               if(reg & 0x01) {        /* DDRII */
+                       buswidth = 32;
+                       if(ivideo->revision_id == 2) {
+                               channelab = 2;
+                               outSISIDXREG(SISSR, 0x13, 0xa1);
+                               outSISIDXREG(SISSR, 0x14, 0x44);
+                               sr14 = 0x04;
+                               sisfb_post_xgi_delay(ivideo, 1);
+                               if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+                                       goto bail_out;
+
+                               outSISIDXREG(SISSR, 0x13, 0x21);
+                               outSISIDXREG(SISSR, 0x14, 0x34);
+                               if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+                                       goto bail_out;
+
+                               channelab = 1;
+                               outSISIDXREG(SISSR, 0x13, 0xa1);
+                               outSISIDXREG(SISSR, 0x14, 0x40);
+                               sr14 = 0x00;
+                               if(sisfb_post_xgi_rwtest(ivideo, 22, 23, mapsize))
+                                       goto bail_out;
+
+                               outSISIDXREG(SISSR, 0x13, 0x21);
+                               outSISIDXREG(SISSR, 0x14, 0x30);
+                       } else {
+                               channelab = 3;
+                               outSISIDXREG(SISSR, 0x13, 0xa1);
+                               outSISIDXREG(SISSR, 0x14, 0x4c);
+                               sr14 = 0x0c;
+                               sisfb_post_xgi_delay(ivideo, 1);
+                               if(sisfb_post_xgi_rwtest(ivideo, 23, 25, mapsize))
+                                       goto bail_out;
+
+                               channelab = 2;
+                               outSISIDXREG(SISSR, 0x14, 0x48);
+                               sisfb_post_xgi_delay(ivideo, 1);
+                               sr14 = 0x08;
+                               if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+                                       goto bail_out;
+
+                               outSISIDXREG(SISSR, 0x13, 0x21);
+                               outSISIDXREG(SISSR, 0x14, 0x3c);
+                               sr14 = 0x0c;
+
+                               if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize)) {
+                                       channelab = 3;
+                               } else {
+                                       channelab = 2;
+                                       outSISIDXREG(SISSR, 0x14, 0x38);
+                                       sr14 = 0x08;
+                               }
+                       }
+                       sisfb_post_xgi_delay(ivideo, 1);
+
+               } else {        /* DDR */
+
+                       buswidth = 64;
+                       if(ivideo->revision_id == 2) {
+                               channelab = 1;
+                               outSISIDXREG(SISSR, 0x13, 0xa1);
+                               outSISIDXREG(SISSR, 0x14, 0x52);
+                               sisfb_post_xgi_delay(ivideo, 1);
+                               sr14 = 0x02;
+                               if(sisfb_post_xgi_rwtest(ivideo, 23, 24, mapsize))
+                                       goto bail_out;
+
+                               outSISIDXREG(SISSR, 0x13, 0x21);
+                               outSISIDXREG(SISSR, 0x14, 0x42);
+                       } else {
+                               channelab = 2;
+                               outSISIDXREG(SISSR, 0x13, 0xa1);
+                               outSISIDXREG(SISSR, 0x14, 0x5a);
+                               sisfb_post_xgi_delay(ivideo, 1);
+                               sr14 = 0x0a;
+                               if(sisfb_post_xgi_rwtest(ivideo, 24, 25, mapsize))
+                                       goto bail_out;
+
+                               outSISIDXREG(SISSR, 0x13, 0x21);
+                               outSISIDXREG(SISSR, 0x14, 0x4a);
+                       }
+                       sisfb_post_xgi_delay(ivideo, 1);
+
+               }
+       }
+
+bail_out:
+       setSISIDXREG(SISSR, 0x14, 0xf0, sr14);
+       sisfb_post_xgi_delay(ivideo, 1);
+
+       j = (ivideo->chip == XGI_20) ? 5 : 9;
+       k = (ivideo->chip == XGI_20) ? 12 : 4;
+
+       for(i = 0; i < k; i++) {
+
+               reg = (ivideo->chip == XGI_20) ?
+                               dramsr13[(i * 5) + 4] : dramsr13_4[(i * 5) + 4];
+               setSISIDXREG(SISSR, 0x13, 0x80, reg);
+               sisfb_post_xgi_delay(ivideo, 50);
+
+               ranksize = (ivideo->chip == XGI_20) ?
+                               dramsr13[(i * 5) + 3] : dramsr13_4[(i * 5) + 3];
+
+               inSISIDXREG(SISSR, 0x13, reg);
+               if(reg & 0x80) ranksize <<= 1;
+
+               if(ivideo->chip == XGI_20) {
+                       if(buswidth == 16)      ranksize <<= 1;
+                       else if(buswidth == 32) ranksize <<= 2;
+               } else {
+                       if(buswidth == 64)      ranksize <<= 1;
+               }
+
+               reg = 0;
+               l = channelab;
+               if(l == 3) l = 4;
+               if((ranksize * l) <= 256) {
+                       while((ranksize >>= 1)) reg += 0x10;
+               }
+
+               if(!reg) continue;
+
+               setSISIDXREG(SISSR, 0x14, 0x0f, (reg & 0xf0));
+               sisfb_post_xgi_delay(ivideo, 1);
+
+               if(sisfb_post_xgi_rwtest(ivideo, j, ((reg >> 4) + channelab - 2 + 20), mapsize))
+                       break;
+       }
+
+       iounmap(ivideo->video_vbase);
+}
 
+static void __devinit
+sisfb_post_xgi_setclocks(struct sis_video_info *ivideo, u8 regb)
+{
+       u8 v1, v2, v3;
+       int index;
+       static const u8 cs90[8 * 3] = {
+               0x16, 0x01, 0x01,
+               0x3e, 0x03, 0x01,
+               0x7c, 0x08, 0x01,
+               0x79, 0x06, 0x01,
+               0x29, 0x01, 0x81,
+               0x5c, 0x23, 0x01,
+               0x5c, 0x23, 0x01,
+               0x5c, 0x23, 0x01
+       };
+       static const u8 csb8[8 * 3] = {
+               0x5c, 0x23, 0x01,
+               0x29, 0x01, 0x01,
+               0x7c, 0x08, 0x01,
+               0x79, 0x06, 0x01,
+               0x29, 0x01, 0x81,
+               0x5c, 0x23, 0x01,
+               0x5c, 0x23, 0x01,
+               0x5c, 0x23, 0x01
+       };
 
-       return 0;
+       regb = 0;  /* ! */
+
+       index = regb * 3;
+       v1 = cs90[index]; v2 = cs90[index + 1]; v3 = cs90[index + 2];
+       if(ivideo->haveXGIROM) {
+               v1 = ivideo->bios_abase[0x90 + index];
+               v2 = ivideo->bios_abase[0x90 + index + 1];
+               v3 = ivideo->bios_abase[0x90 + index + 2];
+       }
+       outSISIDXREG(SISSR, 0x28, v1);
+       outSISIDXREG(SISSR, 0x29, v2);
+       outSISIDXREG(SISSR, 0x2a, v3);
+       sisfb_post_xgi_delay(ivideo, 0x43);
+       sisfb_post_xgi_delay(ivideo, 0x43);
+       sisfb_post_xgi_delay(ivideo, 0x43);
+       index = regb * 3;
+       v1 = csb8[index]; v2 = csb8[index + 1]; v3 = csb8[index + 2];
+       if(ivideo->haveXGIROM) {
+               v1 = ivideo->bios_abase[0xb8 + index];
+               v2 = ivideo->bios_abase[0xb8 + index + 1];
+               v3 = ivideo->bios_abase[0xb8 + index + 2];
+       }
+       outSISIDXREG(SISSR, 0x2e, v1);
+       outSISIDXREG(SISSR, 0x2f, v2);
+       outSISIDXREG(SISSR, 0x30, v3);
+       sisfb_post_xgi_delay(ivideo, 0x43);
+       sisfb_post_xgi_delay(ivideo, 0x43);
+       sisfb_post_xgi_delay(ivideo, 0x43);
 }
-#endif
 
-static UCHAR * __devinit sis_find_rom(struct pci_dev *pdev)
+static int __devinit
+sisfb_post_xgi(struct pci_dev *pdev)
 {
        struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-       USHORT pciid;
-       int    romptr;
-       UCHAR  *myrombase;
-       u32    temp;
-       SIS_IOTYPE1 *rom_base, *rom;
+       unsigned char *bios = ivideo->bios_abase;
+       struct pci_dev *mypdev = NULL;
+       const u8 *ptr, *ptr2;
+       u8 v1, v2, v3, v4, v5, reg, ramtype;
+       u32 rega, regb, regd;
+       int i, j, k, index;
+       static const u8 cs78[3] = { 0xf6, 0x0d, 0x00 };
+       static const u8 cs76[2] = { 0xa3, 0xfb };
+       static const u8 cs7b[3] = { 0xc0, 0x11, 0x00 };
+       static const u8 cs158[8] = {
+               0x88, 0xaa, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs160[8] = {
+               0x44, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs168[8] = {
+               0x48, 0x78, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs128[3 * 8] = {
+               0x90, 0x28, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x77, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs148[2 * 8] = {
+               0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs31a[8 * 4] = {
+               0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+               0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs33a[8 * 4] = {
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs45a[8 * 2] = {
+               0x00, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs170[7 * 8] = {
+               0x54, 0x32, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x54, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x0a, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x44, 0x34, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x10, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x11, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs1a8[3 * 8] = {
+               0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x05, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
+       static const u8 cs100[2 * 8] = {
+               0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0xc4, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
+       };
 
-       if(!(myrombase = vmalloc(65536))) return NULL;
+       /* VGA enable */
+       reg = inSISREG(SISVGAENABLE) | 0x01;
+       outSISREG(SISVGAENABLE, reg);
 
-#if defined(__i386__) || defined(__x86_64__)
+       /* Misc */
+       reg = inSISREG(SISMISCR) | 0x01;
+       outSISREG(SISMISCW, reg);
 
-        for(temp = 0x000c0000; temp < 0x000f0000; temp += 0x00001000) {
+       /* Unlock SR */
+       outSISIDXREG(SISSR, 0x05, 0x86);
+       inSISIDXREG(SISSR, 0x05, reg);
+       if(reg != 0xa1)
+               return 0;
 
-            rom_base = ioremap(temp, 0x10000);
-           if(!rom_base) continue;
+       /* Clear some regs */
+       for(i = 0; i < 0x22; i++) {
+               if(0x06 + i == 0x20) continue;
+               outSISIDXREG(SISSR, 0x06 + i, 0x00);
+       }
+       for(i = 0; i < 0x0b; i++) {
+               outSISIDXREG(SISSR, 0x31 + i, 0x00);
+       }
+       for(i = 0; i < 0x10; i++) {
+               outSISIDXREG(SISCR, 0x30 + i, 0x00);
+       }
 
-           if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
-              iounmap(rom_base);
-               continue;
-           }
+       ptr = cs78;
+       if(ivideo->haveXGIROM) {
+               ptr = (const u8 *)&bios[0x78];
+       }
+       for(i = 0; i < 3; i++) {
+               outSISIDXREG(SISSR, 0x23 + i, ptr[i]);
+       }
 
-           romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
-           if(romptr > (0x10000 - 8)) {
-              iounmap(rom_base);
-              continue;
-           }
+       ptr = cs76;
+       if(ivideo->haveXGIROM) {
+               ptr = (const u8 *)&bios[0x76];
+       }
+       for(i = 0; i < 2; i++) {
+               outSISIDXREG(SISSR, 0x21 + i, ptr[i]);
+       }
 
-           rom = rom_base + romptr;
+       v1 = 0x18; v2 = 0x00;
+       if(ivideo->haveXGIROM) {
+               v1 = bios[0x74];
+               v2 = bios[0x75];
+       }
+       outSISIDXREG(SISSR, 0x07, v1);
+       outSISIDXREG(SISSR, 0x11, 0x0f);
+       outSISIDXREG(SISSR, 0x1f, v2);
+       /* PCI linear mode, RelIO enabled, A0000 decoding disabled */
+       outSISIDXREG(SISSR, 0x20, 0x80 | 0x20 | 0x04);
+       outSISIDXREG(SISSR, 0x27, 0x74);
 
-           if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
-              (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
-              iounmap(rom_base);
-              continue;
-           }
+       ptr = cs7b;
+       if(ivideo->haveXGIROM) {
+               ptr = (const u8 *)&bios[0x7b];
+       }
+       for(i = 0; i < 3; i++) {
+               outSISIDXREG(SISSR, 0x31 + i, ptr[i]);
+       }
 
-           pciid = readb(rom + 4) | (readb(rom + 5) << 8);
-           if(pciid != 0x1039) {
-              iounmap(rom_base);
-              continue;
-           }
+       if(ivideo->chip == XGI_40) {
+               if(ivideo->revision_id == 2) {
+                       setSISIDXREG(SISSR, 0x3b, 0x3f, 0xc0);
+               }
+               outSISIDXREG(SISCR, 0x7d, 0xfe);
+               outSISIDXREG(SISCR, 0x7e, 0x0f);
+       }
+       if(ivideo->revision_id == 0) {  /* 40 *and* 20? */
+               andSISIDXREG(SISCR, 0x58, 0xd7);
+               inSISIDXREG(SISCR, 0xcb, reg);
+               if(reg & 0x20) {
+                       setSISIDXREG(SISCR, 0x58, 0xd7, (reg & 0x10) ? 0x08 : 0x20); /* =0x28 Z7 ? */
+               }
+       }
 
-           pciid = readb(rom + 6) | (readb(rom + 7) << 8);
-           if(pciid == ivideo->chip_id) {
-              memcpy_fromio(myrombase, rom_base, 65536);
-              iounmap(rom_base);
-              return myrombase;
-           }
+       reg = (ivideo->chip == XGI_40) ? 0x20 : 0x00;
+       setSISIDXREG(SISCR, 0x38, 0x1f, reg);
 
-           iounmap(rom_base);
-        }
+       if(ivideo->chip == XGI_20) {
+               outSISIDXREG(SISSR, 0x36, 0x70);
+       } else {
+               outSISIDXREG(SISVID, 0x00, 0x86);
+               outSISIDXREG(SISVID, 0x32, 0x00);
+               outSISIDXREG(SISVID, 0x30, 0x00);
+               outSISIDXREG(SISVID, 0x32, 0x01);
+               outSISIDXREG(SISVID, 0x30, 0x00);
+               andSISIDXREG(SISVID, 0x2f, 0xdf);
+               andSISIDXREG(SISCAP, 0x00, 0x3f);
+
+               outSISIDXREG(SISPART1, 0x2f, 0x01);
+               outSISIDXREG(SISPART1, 0x00, 0x00);
+               outSISIDXREG(SISPART1, 0x02, bios[0x7e]);
+               outSISIDXREG(SISPART1, 0x2e, 0x08);
+               andSISIDXREG(SISPART1, 0x35, 0x7f);
+               andSISIDXREG(SISPART1, 0x50, 0xfe);
+
+               inSISIDXREG(SISPART4, 0x00, reg);
+               if(reg == 1 || reg == 2) {
+                       outSISIDXREG(SISPART2, 0x00, 0x1c);
+                       outSISIDXREG(SISPART4, 0x0d, bios[0x7f]);
+                       outSISIDXREG(SISPART4, 0x0e, bios[0x80]);
+                       outSISIDXREG(SISPART4, 0x10, bios[0x81]);
+                       andSISIDXREG(SISPART4, 0x0f, 0x3f);
+
+                       inSISIDXREG(SISPART4, 0x01, reg);
+                       if((reg & 0xf0) >= 0xb0) {
+                               inSISIDXREG(SISPART4, 0x23, reg);
+                               if(reg & 0x20) reg |= 0x40;
+                               outSISIDXREG(SISPART4, 0x23, reg);
+                               reg = (reg & 0x20) ? 0x02 : 0x00;
+                               setSISIDXREG(SISPART1, 0x1e, 0xfd, reg);
+                       }
+               }
 
-#else
+               v1 = bios[0x77];
+
+               inSISIDXREG(SISSR, 0x3b, reg);
+               if(reg & 0x02) {
+                       inSISIDXREG(SISSR, 0x3a, reg);
+                       v2 = (reg & 0x30) >> 3;
+                       if(!(v2 & 0x04)) v2 ^= 0x02;
+                       inSISIDXREG(SISSR, 0x39, reg);
+                       if(reg & 0x80) v2 |= 0x80;
+                       v2 |= 0x01;
+
+                       if((mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0730, NULL))) {
+                               SIS_PCI_PUT_DEVICE(mypdev);
+                               if(((v2 & 0x06) == 2) || ((v2 & 0x06) == 4))
+                                       v2 &= 0xf9;
+                               v2 |= 0x08;
+                               v1 &= 0xfe;
+                       } else {
+                               mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0735, NULL);
+                               if(!mypdev)
+                                       mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0645, NULL);
+                               if(!mypdev)
+                                       mypdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0650, NULL);
+                               if(mypdev) {
+                                       pci_read_config_dword(mypdev, 0x94, &regd);
+                                       regd &= 0xfffffeff;
+                                       pci_write_config_dword(mypdev, 0x94, regd);
+                                       v1 &= 0xfe;
+                                       SIS_PCI_PUT_DEVICE(mypdev);
+                               } else if(sisfb_find_host_bridge(ivideo, pdev, PCI_VENDOR_ID_SI)) {
+                                       v1 &= 0xfe;
+                               } else if(sisfb_find_host_bridge(ivideo, pdev, 0x1106) ||
+                                         sisfb_find_host_bridge(ivideo, pdev, 0x1022) ||
+                                         sisfb_find_host_bridge(ivideo, pdev, 0x700e) ||
+                                         sisfb_find_host_bridge(ivideo, pdev, 0x10de)) {
+                                       if((v2 & 0x06) == 4)
+                                               v2 ^= 0x06;
+                                       v2 |= 0x08;
+                               }
+                       }
+                       setSISIDXREG(SISCR, 0x5f, 0xf0, v2);
+               }
+               outSISIDXREG(SISSR, 0x22, v1);
+
+               if(ivideo->revision_id == 2) {
+                       inSISIDXREG(SISSR, 0x3b, v1);
+                       inSISIDXREG(SISSR, 0x3a, v2);
+                       regd = bios[0x90 + 3] | (bios[0x90 + 4] << 8);
+                       if( (!(v1 & 0x02)) && (v2 & 0x30) && (regd < 0xcf) )
+                               setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+
+                       if((mypdev = SIS_PCI_GET_DEVICE(0x10de, 0x01e0, NULL))) {
+                               /* TODO: set CR5f &0xf1 | 0x01 for version 6570
+                                * of nforce 2 ROM
+                                */
+                               if(0)
+                                       setSISIDXREG(SISCR, 0x5f, 0xf1, 0x01);
+                               SIS_PCI_PUT_DEVICE(mypdev);
+                       }
+               }
 
-       pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &temp);
-       pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
-                       (ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+               v1 = 0x30;
+               inSISIDXREG(SISSR, 0x3b, reg);
+               inSISIDXREG(SISCR, 0x5f, v2);
+               if((!(reg & 0x02)) && (v2 & 0x0e))
+                       v1 |= 0x08;
+               outSISIDXREG(SISSR, 0x27, v1);
 
-       rom_base = ioremap(ivideo->video_base, 65536);
-       if(rom_base) {
-          if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
-             romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
-             if(romptr <= (0x10000 - 8)) {
-                rom = rom_base + romptr;
-                if((readb(rom)     == 'P') && (readb(rom + 1) == 'C') &&
-                   (readb(rom + 2) == 'I') && (readb(rom + 3) == 'R')) {
-                   pciid = readb(rom + 4) | (readb(rom + 5) << 8);
-                   if(pciid == 0x1039) {
-                      pciid = readb(rom + 6) | (readb(rom + 7) << 8);
-                      if(pciid == ivideo->chip_id) {
-                         memcpy_fromio(myrombase, rom_base, 65536);
-                         iounmap(rom_base);
-                         pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
-                         return myrombase;
-                      }
-                   }
-                }
-             }
-          }
-          iounmap(rom_base);
+               if(bios[0x64] & 0x01) {
+                       setSISIDXREG(SISCR, 0x5f, 0xf0, bios[0x64]);
+               }
+
+               v1 = bios[0x4f7];
+               pci_read_config_dword(pdev, 0x50, &regd);
+               regd = (regd >> 20) & 0x0f;
+               if(regd == 1) {
+                       v1 &= 0xfc;
+                       orSISIDXREG(SISCR, 0x5f, 0x08);
+               }
+               outSISIDXREG(SISCR, 0x48, v1);
+
+               setSISIDXREG(SISCR, 0x47, 0x04, bios[0x4f6] & 0xfb);
+               setSISIDXREG(SISCR, 0x49, 0xf0, bios[0x4f8] & 0x0f);
+               setSISIDXREG(SISCR, 0x4a, 0x60, bios[0x4f9] & 0x9f);
+               setSISIDXREG(SISCR, 0x4b, 0x08, bios[0x4fa] & 0xf7);
+               setSISIDXREG(SISCR, 0x4c, 0x80, bios[0x4fb] & 0x7f);
+               outSISIDXREG(SISCR, 0x70, bios[0x4fc]);
+               setSISIDXREG(SISCR, 0x71, 0xf0, bios[0x4fd] & 0x0f);
+               outSISIDXREG(SISCR, 0x74, 0xd0);
+               setSISIDXREG(SISCR, 0x74, 0xcf, bios[0x4fe] & 0x30);
+               setSISIDXREG(SISCR, 0x75, 0xe0, bios[0x4ff] & 0x1f);
+               setSISIDXREG(SISCR, 0x76, 0xe0, bios[0x500] & 0x1f);
+               v1 = bios[0x501];
+               if((mypdev = SIS_PCI_GET_DEVICE(0x8086, 0x2530, NULL))) {
+                       v1 = 0xf0;
+                       SIS_PCI_PUT_DEVICE(mypdev);
+               }
+               outSISIDXREG(SISCR, 0x77, v1);
        }
-        pci_write_config_dword(pdev, PCI_ROM_ADDRESS, temp);
 
-#endif
+       /* RAM type */
 
-               vfree(myrombase);
-        return NULL;
-}
+       regb = 0;       /* ! */
 
-#ifdef CONFIG_FB_SIS_300
-static int __devinit
-sisfb_chkbuswidth300(struct pci_dev *pdev, SIS_IOTYPE1 *FBAddress)
-{
-       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-       int i, j;
-       USHORT temp;
-       UCHAR reg;
-
-       andSISIDXREG(SISSR,0x15,0xFB);
-       orSISIDXREG(SISSR,0x15,0x04);
-       outSISIDXREG(SISSR,0x13,0x00);
-       outSISIDXREG(SISSR,0x14,0xBF);
-
-       for(i=0; i<2; i++) {
-          temp = 0x1234;
-          for(j=0; j<4; j++) {
-             writew(temp, FBAddress);
-             if(readw(FBAddress) == temp) break;
-             orSISIDXREG(SISSR,0x3c,0x01);
-             inSISIDXREG(SISSR,0x05,reg);
-             inSISIDXREG(SISSR,0x05,reg);
-             andSISIDXREG(SISSR,0x3c,0xfe);
-             inSISIDXREG(SISSR,0x05,reg);
-             inSISIDXREG(SISSR,0x05,reg);
-             temp++;
-          }
+       v1 = 0xff;
+       if(ivideo->haveXGIROM) {
+               v1 = bios[0x140 + regb];
        }
+       outSISIDXREG(SISCR, 0x6d, v1);
 
-       writel(0x01234567L, FBAddress);
-       writel(0x456789ABL, (FBAddress+4));
-       writel(0x89ABCDEFL, (FBAddress+8));
-       writel(0xCDEF0123L, (FBAddress+12));
-       inSISIDXREG(SISSR,0x3b,reg);
-       if(reg & 0x01) {
-          if(readl((FBAddress+12)) == 0xCDEF0123L) return(4);  /* Channel A 128bit */
+       ptr = cs128;
+       if(ivideo->haveXGIROM) {
+               ptr = (const u8 *)&bios[0x128];
        }
-       if(readl((FBAddress+4)) == 0x456789ABL)     return(2);  /* Channel B 64bit */
-       return(1);                                              /* 32bit */
-}
-
-static void __devinit
-sisfb_setramsize300(struct pci_dev *pdev)
-{
-       struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
-       SIS_IOTYPE1 *FBAddr = ivideo->video_vbase;
-       SIS_IOTYPE1 *Addr;
-       USHORT  sr13, sr14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
-       int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
-       int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
-       int     PageCapacity, PhysicalAdrHigh, PhysicalAdrHalfPage, i, j, k;
-       const   USHORT SiS_DRAMType[17][5] = {
-                       {0x0C,0x0A,0x02,0x40,0x39},
-                       {0x0D,0x0A,0x01,0x40,0x48},
-                       {0x0C,0x09,0x02,0x20,0x35},
-                       {0x0D,0x09,0x01,0x20,0x44},
-                       {0x0C,0x08,0x02,0x10,0x31},
-                       {0x0D,0x08,0x01,0x10,0x40},
-                       {0x0C,0x0A,0x01,0x20,0x34},
-                       {0x0C,0x09,0x01,0x08,0x32},
-                       {0x0B,0x08,0x02,0x08,0x21},
-                       {0x0C,0x08,0x01,0x08,0x30},
-                       {0x0A,0x08,0x02,0x04,0x11},
-                       {0x0B,0x0A,0x01,0x10,0x28},
-                       {0x09,0x08,0x02,0x02,0x01},
-                       {0x0B,0x09,0x01,0x08,0x24},
-                       {0x0B,0x08,0x01,0x04,0x20},
-                       {0x0A,0x08,0x01,0x02,0x10},
-                       {0x09,0x08,0x01,0x01,0x00}
-               };
-
-        buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
-
-       MB2Bank = 16;
-       Done = 0;
-       for(i = 6; i >= 0; i--) {
-          if(Done) break;
-          PseudoRankCapacity = 1 << i;
-          for(j = 4; j >= 1; j--) {
-              if(Done) break;
-              PseudoTotalCapacity = PseudoRankCapacity * j;
-              PseudoAdrPinCount = 15 - j;
-              if(PseudoTotalCapacity <= 64) {
-                 for(k = 0; k <= 16; k++) {
-                    if(Done) break;
-                    RankCapacity = buswidth * SiS_DRAMType[k][3];
-                    AdrPinCount = SiS_DRAMType[k][2] + SiS_DRAMType[k][0];
-                    if(RankCapacity == PseudoRankCapacity)
-                       if(AdrPinCount <= PseudoAdrPinCount) {
-                          if(j == 3) {             /* Rank No */
-                             BankNumHigh = RankCapacity * MB2Bank * 3 - 1;
-                             BankNumMid  = RankCapacity * MB2Bank * 1 - 1;
-                          } else {
-                             BankNumHigh = RankCapacity * MB2Bank * j - 1;
-                             BankNumMid  = RankCapacity * MB2Bank * j / 2 - 1;
-                          }
-                          PageCapacity = (1 << SiS_DRAMType[k][1]) * buswidth * 4;
-                          PhysicalAdrHigh = BankNumHigh;
-                          PhysicalAdrHalfPage = (PageCapacity / 2 + PhysicalAdrHigh) % PageCapacity;
-                          PhysicalAdrOtherPage = PageCapacity * SiS_DRAMType[k][2] + PhysicalAdrHigh;
-                          /* Write data */
-                          andSISIDXREG(SISSR,0x15,0xFB); /* Test */
-                          orSISIDXREG(SISSR,0x15,0x04);  /* Test */
-                          TotalCapacity = SiS_DRAMType[k][3] * buswidth;
-                          sr13 = SiS_DRAMType[k][4];
-                          if(buswidth == 4) sr14 = (TotalCapacity - 1) | 0x80;
-                          if(buswidth == 2) sr14 = (TotalCapacity - 1) | 0x40;
-                          if(buswidth == 1) sr14 = (TotalCapacity - 1) | 0x00;
-                          outSISIDXREG(SISSR,0x13,sr13);
-                          outSISIDXREG(SISSR,0x14,sr14);
-                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
-                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHigh; */
-                         writew(((USHORT)PhysicalAdrHigh), Addr);
-                          Addr = FBAddr + BankNumMid * 64 * 1024 + PhysicalAdrHigh;
-                          /* *((USHORT *)(Addr)) = (USHORT)BankNumMid; */
-                         writew(((USHORT)BankNumMid), Addr);
-                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHalfPage;
-                          /* *((USHORT *)(Addr)) = (USHORT)PhysicalAdrHalfPage; */
-                         writew(((USHORT)PhysicalAdrHalfPage), Addr);
-                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrOtherPage;
-                          /* *((USHORT *)(Addr)) = PhysicalAdrOtherPage; */
-                         writew(((USHORT)PhysicalAdrOtherPage), Addr);
-                          /* Read data */
-                          Addr = FBAddr + BankNumHigh * 64 * 1024 + PhysicalAdrHigh;
-                          data = readw(Addr); /* *((USHORT *)(Addr)); */
-                          if(data == PhysicalAdrHigh) Done = 1;
-                       }  /* if */
-                 }  /* for k */
-              }  /* if */
-          }  /* for j */
-       }  /* for i */
-}
-
-static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
-{
-       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-       u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
-       u16 index, rindex, memtype = 0;
-
-       outSISIDXREG(SISSR,0x05,0x86);
-
-       if(ivideo->sishw_ext.UseROM) {
-          if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
-             memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
-          } else {
-             inSISIDXREG(SISSR,0x3a,memtype);
-          }
-          memtype &= 0x07;
+       for(i = 0, j = 0; i < 3; i++, j += 8) {
+               outSISIDXREG(SISCR, 0x68 + i, ptr[j + regb]);
        }
 
-       if(ivideo->revision_id <= 0x13) {
-          v1 = 0x44; v2 = 0x42; v3 = 0x80;
-          v4 = 0x44; v5 = 0x42; v6 = 0x80;
-       } else {
-          v1 = 0x68; v2 = 0x43; v3 = 0x80;  /* Assume 125Mhz MCLK */
-          v4 = 0x68; v5 = 0x43; v6 = 0x80;  /* Assume 125Mhz ECLK */
-          if(ivideo->sishw_ext.UseROM) {
-             index = memtype * 5;
-             rindex = index + 0x54;
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-             v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-             v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-             rindex = index + 0x7c;
-             v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-             v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-             v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-          }
+       ptr  = cs31a;
+       ptr2 = cs33a;
+       if(ivideo->haveXGIROM) {
+               index = (ivideo->chip == XGI_20) ? 0x31a : 0x3a6;
+               ptr  = (const u8 *)&bios[index];
+               ptr2 = (const u8 *)&bios[index + 0x20];
        }
-       outSISIDXREG(SISSR,0x28,v1);
-       outSISIDXREG(SISSR,0x29,v2);
-       outSISIDXREG(SISSR,0x2a,v3);
-       outSISIDXREG(SISSR,0x2e,v4);
-       outSISIDXREG(SISSR,0x2f,v5);
-       outSISIDXREG(SISSR,0x30,v6);
-       v1 = 0x10;
-       if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
-       outSISIDXREG(SISSR,0x07,v1);       /* DAC speed */
-       outSISIDXREG(SISSR,0x11,0x0f);     /* DDC, power save */
-       v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
-       v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
-       if(ivideo->sishw_ext.UseROM) {
-          memtype += 0xa5;
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
-          v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
-          v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
-          v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
-          v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
-          v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
-          v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
-       }
-       if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
-       outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
-       outSISIDXREG(SISSR,0x16,v2);
-       outSISIDXREG(SISSR,0x17,v3);
-       outSISIDXREG(SISSR,0x18,v4);
-       outSISIDXREG(SISSR,0x19,v5);
-       outSISIDXREG(SISSR,0x1a,v6);
-       outSISIDXREG(SISSR,0x1b,v7);
-       outSISIDXREG(SISSR,0x1c,v8);       /* ---- */
-       andSISIDXREG(SISSR,0x15,0xfb);
-       orSISIDXREG(SISSR,0x15,0x04);
-       if(ivideo->sishw_ext.UseROM) {
-          if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
-             orSISIDXREG(SISSR,0x19,0x20);
-          }
+       for(i = 0; i < 2; i++) {
+               if(i == 0) {
+                       regd = le32_to_cpu(((u32 *)ptr)[regb]);
+                       rega = 0x6b;
+               } else {
+                       regd = le32_to_cpu(((u32 *)ptr2)[regb]);
+                       rega = 0x6e;
+               }
+               reg = 0x00;
+               for(j = 0; j < 16; j++) {
+                       reg &= 0xf3;
+                       if(regd & 0x01) reg |= 0x04;
+                       if(regd & 0x02) reg |= 0x08;
+                       regd >>= 2;
+                       outSISIDXREG(SISCR, rega, reg);
+                       inSISIDXREG(SISCR, rega, reg);
+                       inSISIDXREG(SISCR, rega, reg);
+                       reg += 0x10;
+               }
        }
-       v1 = 0x04;                         /* DAC pedestal (BIOS 0xe5) */
-       if(ivideo->revision_id >= 0x80) v1 |= 0x01;
-       outSISIDXREG(SISSR,0x1f,v1);
-       outSISIDXREG(SISSR,0x20,0xa0);     /* linear & relocated io */
-       v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
-          v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
-       }
-       outSISIDXREG(SISSR,0x23,v1);
-       outSISIDXREG(SISSR,0x24,v2);
-       outSISIDXREG(SISSR,0x25,v3);
-       outSISIDXREG(SISSR,0x21,0x84);
-       outSISIDXREG(SISSR,0x22,0x00);
-       outSISIDXREG(SISCR,0x37,0x00);
-       orSISIDXREG(SISPART1,0x24,0x01);   /* unlock crt2 */
-       outSISIDXREG(SISPART1,0x00,0x00);
-       v1 = 0x40; v2 = 0x11;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
+
+       andSISIDXREG(SISCR, 0x6e, 0xfc);
+
+       ptr  = NULL;
+       if(ivideo->haveXGIROM) {
+               index = (ivideo->chip == XGI_20) ? 0x35a : 0x3e6;
+               ptr  = (const u8 *)&bios[index];
        }
-       outSISIDXREG(SISPART1,0x02,v1);
-       if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
-       inSISIDXREG(SISPART4,0x00,reg);
-       if((reg == 1) || (reg == 2)) {
-          outSISIDXREG(SISCR,0x37,0x02);
-          outSISIDXREG(SISPART2,0x00,0x1c);
-          v4 = 0x00; v5 = 0x00; v6 = 0x10;
-          if(ivideo->sishw_ext.UseROM) {
-             v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
-             v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
-             v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
-          }
-          outSISIDXREG(SISPART4,0x0d,v4);
-          outSISIDXREG(SISPART4,0x0e,v5);
-          outSISIDXREG(SISPART4,0x10,v6);
-          outSISIDXREG(SISPART4,0x0f,0x3f);
-          inSISIDXREG(SISPART4,0x01,reg);
-          if(reg >= 0xb0) {
-             inSISIDXREG(SISPART4,0x23,reg);
-             reg &= 0x20;
-             reg <<= 1;
-             outSISIDXREG(SISPART4,0x23,reg);
-          }
-       } else {
-          v2 &= ~0x10;
+       for(i = 0; i < 4; i++) {
+               setSISIDXREG(SISCR, 0x6e, 0xfc, i);
+               reg = 0x00;
+               for(j = 0; j < 2; j++) {
+                       regd = 0;
+                       if(ptr) {
+                               regd = le32_to_cpu(((u32 *)ptr)[regb * 8]);
+                               ptr += 4;
+                       }
+                       /* reg = 0x00; */
+                       for(k = 0; k < 16; k++) {
+                               reg &= 0xfc;
+                               if(regd & 0x01) reg |= 0x01;
+                               if(regd & 0x02) reg |= 0x02;
+                               regd >>= 2;
+                               outSISIDXREG(SISCR, 0x6f, reg);
+                               inSISIDXREG(SISCR, 0x6f, reg);
+                               inSISIDXREG(SISCR, 0x6f, reg);
+                               reg += 0x08;
+                       }
+               }
        }
-       outSISIDXREG(SISSR,0x32,v2);
-       andSISIDXREG(SISPART1,0x24,0xfe);  /* Lock CRT2 */
-       inSISIDXREG(SISSR,0x16,reg);
-       reg &= 0xc3;
-       outSISIDXREG(SISCR,0x35,reg);
-       outSISIDXREG(SISCR,0x83,0x00);
-#if !defined(__i386__) && !defined(__x86_64__)
-       if(sisfb_videoram) {
-          outSISIDXREG(SISSR,0x13,0x28);  /* ? */
-          reg = ((sisfb_videoram >> 10) - 1) | 0x40;
-          outSISIDXREG(SISSR,0x14,reg);
-       } else {
-#endif
-          /* Need to map max FB size for finding out about RAM size */
-          ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
-          if(ivideo->video_vbase) {
-             sisfb_setramsize300(pdev);
-             iounmap(ivideo->video_vbase);
-          } else {
-             printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
-             outSISIDXREG(SISSR,0x13,0x28);  /* ? */
-             outSISIDXREG(SISSR,0x14,0x47);  /* 8MB, 64bit default */
-          }
-#if !defined(__i386__) && !defined(__x86_64__)
+
+       ptr  = cs148;
+       if(ivideo->haveXGIROM) {
+               ptr  = (const u8 *)&bios[0x148];
        }
-#endif
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
-       } else {
-          inSISIDXREG(SISSR,0x3a,reg);
-          if((reg & 0x30) == 0x30) {
-             v1 = 0x04; /* PCI */
-             v2 = 0x92;
-          } else {
-             v1 = 0x14; /* AGP */
-             v2 = 0xb2;
-          }
+       for(i = 0, j = 0; i < 2; i++, j += 8) {
+               outSISIDXREG(SISCR, 0x80 + i, ptr[j + regb]);
        }
-       outSISIDXREG(SISSR,0x21,v1);
-       outSISIDXREG(SISSR,0x22,v2);
-}
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-static void __devinit sisfb_post_sis315330(struct pci_dev *pdev)
-{
-#ifdef YET_TO_BE_DONE
-       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-       u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
-       u16 index, rindex, memtype = 0;
-       u32 reg1_32, reg2_32, reg3_32;
-       int i;
 
-       /* Unlock */
-       /* outSISIDXREG(0x3c4,0x05,0x86); */
-       outSISIDXREG(SISSR,0x05,0x86);
+       andSISIDXREG(SISCR, 0x89, 0x8f);
 
-       /* Enable relocated i/o ports */
-       /* setSISIDXREG(0x3c4,0x20,~0x10,0x20); */
-       setSISIDXREG(SISSR,0x20,~0x10,0x20);
+       ptr  = cs45a;
+       if(ivideo->haveXGIROM) {
+               index = (ivideo->chip == XGI_20) ? 0x45a : 0x4e6;
+               ptr  = (const u8 *)&bios[index];
+       }
+       regd = le16_to_cpu(((const u16 *)ptr)[regb]);
+       reg = 0x80;
+       for(i = 0; i < 5; i++) {
+               reg &= 0xfc;
+               if(regd & 0x01) reg |= 0x01;
+               if(regd & 0x02) reg |= 0x02;
+               regd >>= 2;
+               outSISIDXREG(SISCR, 0x89, reg);
+               inSISIDXREG(SISCR, 0x89, reg);
+               inSISIDXREG(SISCR, 0x89, reg);
+               reg += 0x10;
+       }
 
-       /* Clear regs */
-       for(i = 0; i < 0x22; i++) {
-          outSISIDXREG(SISSR,(0x06 + i),0x00);
+       v1 = 0xb5; v2 = 0x20; v3 = 0xf0; v4 = 0x13;
+       if(ivideo->haveXGIROM) {
+               v1 = bios[0x118 + regb];
+               v2 = bios[0xf8 + regb];
+               v3 = bios[0x120 + regb];
+               v4 = bios[0x1ca];
        }
-       v1 = 0x0d;
-       if( is 330) v1 = 0x0b;
-       for(i = 0; i < v1; i++) {
-          outSISIDXREG(SISSR,(0x31 + i),0x00);
+       outSISIDXREG(SISCR, 0x45, v1 & 0x0f);
+       outSISIDXREG(SISCR, 0x99, (v1 >> 4) & 0x07);
+       orSISIDXREG(SISCR, 0x40, v1 & 0x80);
+       outSISIDXREG(SISCR, 0x41, v2);
+
+       ptr  = cs170;
+       if(ivideo->haveXGIROM) {
+               ptr  = (const u8 *)&bios[0x170];
        }
-       for(i = 0; i < 0x10; i++) {
-          outSISIDXREG(SISCR,(0x30 + i),0x00);
-       }
-
-       /* Reset clocks */
-       reg = inSISREG(SISMISCR);
-       outSISIDXREG(SISSR,0x28,0x81);
-       outSISIDXREG(SISSR,0x2A,0x00);
-       outSISIDXREG(SISSR,0x29,0xE1);
-       outSISREG(SISMISCW,(reg | 0x0c));
-       outSISIDXREG(SISSR,0x2B,0x81);
-       outSISIDXREG(SISSR,0x2D,0x00);
-       outSISIDXREG(SISSR,0x2C,0xE1);
-       outSISIDXREG(SISSR,0x2E,0x81);
-       outSISIDXREG(SISSR,0x30,0x00);
-       outSISIDXREG(SISSR,0x2F,0xE1);
-       SiS_DDC2Delay(....);
-       outSISREG(SISMISCW,reg);
-
-       /* Get memory type */
-       if(ivideo->sishw_ext.UseROM) {
-          if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80)) {
-             memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
-          } else {
-             inSISIDXREG(SISSR,0x3a,memtype);
-          }
-          memtype &= 0x03;
-          if( is 330 ) {
-             if(memtype <= 1) memtype = 0;
-             else {
-                inSISIDXREG(SISCR,0x5F,reg);
-                reg &= 0x30;
-                switch(reg) {
-                case 0x00: memtype = 1; break;
-                case 0x10: memtype = 3; break;
-                case 0x20: memtype = 3; break;
-                default:   memtype = 2;
-                }
-             }
-          }
+       for(i = 0, j = 0; i < 7; i++, j += 8) {
+               outSISIDXREG(SISCR, 0x90 + i, ptr[j + regb]);
        }
 
-       /* Set clocks */
-       v1 = 0x3b; v2 = 0x22; v3 = 0x01;  /* Assume 143Mhz MCLK */
-       v4 = 0x5c; v5 = 0x23; v6 = 0x01;  /* Assume 166Mhz ECLK */
-       if(ivideo->sishw_ext.UseROM) {
-          index = memtype * 5;
-          rindex = index + 0x54;
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-          v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-          rindex = index + 0x68;
-          v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-          v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-          v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
-       }
-       outSISIDXREG(SISSR,0x28,v1);
-       outSISIDXREG(SISSR,0x29,v2);
-       outSISIDXREG(SISSR,0x2a,v3);
-       if( is 330 ) {
-          inSISIDXREG(SISSR,0x3a,reg);
-          reg &= 0x03;
-          if(reg >= 2) {
-             ...
-          }
+       outSISIDXREG(SISCR, 0x59, v3);
+
+       ptr  = cs1a8;
+       if(ivideo->haveXGIROM) {
+               ptr  = (const u8 *)&bios[0x1a8];
+       }
+       for(i = 0, j = 0; i < 3; i++, j += 8) {
+               outSISIDXREG(SISCR, 0xc3 + i, ptr[j + regb]);
        }
-       outSISIDXREG(SISSR,0x2e,v4);
-       outSISIDXREG(SISSR,0x2f,v5);
-       outSISIDXREG(SISSR,0x30,v6);
-
-       /* End of comp with 330 */
-
-       v1 = 0x18;
-       if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0x7c];
-       outSISIDXREG(SISSR,0x07,v1);
-       outSISIDXREG(SISSR,0x11,0x0f);
-
-       v1 = 0x00; v2 = 0x0f; v3 = 0xba; v4 = 0xa9;
-       v5 = 0xa0; v6 = 0x00; v7 = 0x30;
-       if(ivideo->sishw_ext.UseROM) {
-          index = memtype + 0x7d;
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
-          v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
-          v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
-          v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
-          v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
-          v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
-       }
-       outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0x7d step 4) */
-       outSISIDXREG(SISSR,0x16,v2);
-       outSISIDXREG(SISSR,0x17,v3);
-       outSISIDXREG(SISSR,0x18,v4);
-       outSISIDXREG(SISSR,0x19,v5);
-       outSISIDXREG(SISSR,0x1a,v6);
-       outSISIDXREG(SISSR,0x1b,v7);
-       outSISIDXREG(SISSR,0x1c,v8);       /* ---- */
-
-       v1 = 0x77; v2 = 0x77; v3 = 0x00; v4 = 0x5b; v5 = 0x00;
-       if(ivideo->sishw_ext.UseROM) {
-          index = memtype + 0xa2;
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
-          v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
-          v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
-          v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
-       }
-       outSISIDXREG(SISCR,0x40,v1);
-       outSISIDXREG(SISCR,0x41,v2);
-       outSISIDXREG(SISCR,0x42,v3);
-       outSISIDXREG(SISCR,0x43,v4);
-       outSISIDXREG(SISCR,0x44,v5);
-
-       if( is 330 ) {
-
-          v1 = 0x;
-          if(ivideo->sishw_ext.UseROM) {
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
-          }
-          outSISIDXREG(SISCR,0x59,v1);
-
-          v1 = 0x; v2 = 0x; v3 = 0x; v4 = 0x;
-          v5 = 0x; v6 = 0x; v7 = 0x; v8 = 0x;
-          if(ivideo->sishw_ext.UseROM) {
-             index = memtype + 0xbe;
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[index];
-             v2 = ivideo->sishw_ext.pjVirtualRomBase[index + 4];
-             v3 = ivideo->sishw_ext.pjVirtualRomBase[index + 8];
-             v4 = ivideo->sishw_ext.pjVirtualRomBase[index + 12];
-             v5 = ivideo->sishw_ext.pjVirtualRomBase[index + 16];
-             v6 = ivideo->sishw_ext.pjVirtualRomBase[index + 20];
-             v7 = ivideo->sishw_ext.pjVirtualRomBase[index + 24];
-             v8 = ivideo->sishw_ext.pjVirtualRomBase[index + 28];
-          }
-          outSISIDXREG(SISCR,0x68,v1);
-          outSISIDXREG(SISCR,0x69,v2);
-          outSISIDXREG(SISCR,0x6a,v3);
-          outSISIDXREG(SISCR,0x6b,v4);
-          outSISIDXREG(SISCR,0x6c,v5);
-          outSISIDXREG(SISCR,0x6d,v6);
-          outSISIDXREG(SISCR,0x6e,v7);
-          outSISIDXREG(SISCR,0x6f,v8);
-
-          v1 = 0x20;
-          inSISIDXREG(SISSR,0x3b,reg);
-
-          if(!(reg & 0x04)) {
-             inSISIDXREG(SISCR,0x5F,reg);
-             reg &= 0x30;
-             if(reg) v1 = 0x23;
-          }
-          outSISIDXREG(SISCR,0x48,v1);
-          outSISIDXREG(SISCR,0x4c,0x20);
-
-          xx= xxx();
-          if(xx >= 1) {
-             v1 = 0x;
-             if(ivideo->sishw_ext.UseROM) {
-                v1 = ivideo->sishw_ext.pjVirtualRomBase[0xBA];
-             }
-             outSISIDXREG(SISCR,0x59,v1);
-          }
 
+       ptr  = cs100;
+       if(ivideo->haveXGIROM) {
+               ptr  = (const u8 *)&bios[0x100];
+       }
+       for(i = 0, j = 0; i < 2; i++, j += 8) {
+               outSISIDXREG(SISCR, 0x8a + i, ptr[j + regb]);
+       }
 
+       outSISIDXREG(SISCR, 0xcf, v4);
 
-       } else {
+       outSISIDXREG(SISCR, 0x83, 0x09);
+       outSISIDXREG(SISCR, 0x87, 0x00);
 
-          outSISIDXREG(SISCR,0x48,0x23);
+       if(ivideo->chip == XGI_40) {
+               if( (ivideo->revision_id == 1) ||
+                   (ivideo->revision_id == 2) ) {
+                       outSISIDXREG(SISCR, 0x8c, 0x87);
+               }
+       }
 
-          andSISIDXREG(SISSR,0x16,0x0f);
-          if(memtype <= 1) {
-             orSISIDXREG(SISSR,0x16,0x80);
-          } else {
-             v1 = 0x0f;
-             if(ivideo->sishw_ext.UseROM) {
-                v1 = ivideo->sishw_ext.pjVirtualRomBase[0x81 + memtype];
-             }
-             if(!(v1 & 0x10)) v2 = 0xc0;
-             else             v2 = 0xd0;
-             orSISIDXREG(SISSR,0x16,v2);
-             andSISIDXREG(SISSR,0x16,0x0f);
-             if(!(v1 & 0x10)) v2 = 0x80;
-             else             v2 = 0xA0;
-             orSISIDXREG(SISSR,0x16,v2);
-          }
-
-          if(memtype >= 2) {
-             const u8 sr3cseq1[] = { 0xc0,0xe0,0xf0,0xe0,0xf0,0xa0,0xb0,0xa0,0xb0,0x90,0xd0 };
-             const u8 sr3cseq2[] = { 0xc0,0xa0,0xb0,0xa0,0xb0,0xe0,0xf0,0xa0,0xb0,0x90,0xd0 };
-             for(i = 0; i < 11; i++) {
-                outSISIDXREG(SISSR,0x3c,sr3cseq1[i]);
-             }
-             outSISIDXREG(SISSR,0x3d,0x00);
-             outSISIDXREG(SISSR,0x3d,0x04);
-             SiS_DDC2Delay(0x200);
-             v1 = inSISIDXREG(SISCR,0xEC);
-             v2 = inSISIDXREG(SISCR,0xED);
-             reg1_32 = (v2 << 8) | v1;
-             outSISIDXREG(SISSR,0x3D,0x00);
-             for(i = 0; i < 11; i++) {
-                outSISIDXREG(SISSR,0x3c,sr3cseq2[i]);
-             }
-             outSISIDXREG(SISSR,0x3d,0x00);
-             outSISIDXREG(SISSR,0x3d,0x04);
-             SiS_DDC2Delay(0x200);
-             v1 = inSISIDXREG(SISCR,0xEC);
-             v2 = inSISIDXREG(SISCR,0xED);
-             reg2_32 = (v2 << 8) | v1;
-             outSISIDXREG(SISSR,0x3D,0x00);
-             reg3_32 = reg2_32 << 1;
-             reg2_32 >>= 1;
-             reg3_32 += reg2_32;
-             v1 = 0x40;
-             if(reg3_32 > reg1_32) v1 = 0x10;
-                outSISIDXREG(SISCR,0x59,v1);
-          }
+       outSISIDXREG(SISSR, 0x17, 0x00);
+       outSISIDXREG(SISSR, 0x1a, 0x87);
 
+       if(ivideo->chip == XGI_20) {
+               outSISIDXREG(SISSR, 0x15, 0x00);
+               outSISIDXREG(SISSR, 0x1c, 0x00);
        }
 
-       v1 = 0x00;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0x99];
+       ramtype = 0x00; v1 = 0x10;
+       if(ivideo->haveXGIROM) {
+               ramtype = bios[0x62];
+               v1 = bios[0x1d2];
+       }
+       if(!(ramtype & 0x80)) {
+               if(ivideo->chip == XGI_20) {
+                       outSISIDXREG(SISCR, 0x97, v1);
+                       inSISIDXREG(SISCR, 0x97, reg);
+                       if(reg & 0x10) {
+                               ramtype = (reg & 0x01) << 1;
+                       }
+               } else {
+                       inSISIDXREG(SISSR, 0x39, reg);
+                       ramtype = reg & 0x02;
+                       if(!(ramtype)) {
+                               inSISIDXREG(SISSR, 0x3a, reg);
+                               ramtype = (reg >> 1) & 0x01;
+                       }
+               }
        }
-       outSISIDXREG(SISSR,0x1f,v1);
+       ramtype &= 0x07;
+
+       regb = 0;       /* ! */
+
+       switch(ramtype) {
+       case 0:
+               sisfb_post_xgi_setclocks(ivideo, regb);
+               if((ivideo->chip == XGI_20) ||
+                  (ivideo->revision_id == 1)   ||
+                  (ivideo->revision_id == 2)) {
+                       v1 = cs158[regb]; v2 = cs160[regb]; v3 = cs168[regb];
+                       if(ivideo->haveXGIROM) {
+                               v1 = bios[regb + 0x158];
+                               v2 = bios[regb + 0x160];
+                               v3 = bios[regb + 0x168];
+                       }
+                       outSISIDXREG(SISCR, 0x82, v1);
+                       outSISIDXREG(SISCR, 0x85, v2);
+                       outSISIDXREG(SISCR, 0x86, v3);
+               } else {
+                       outSISIDXREG(SISCR, 0x82, 0x88);
+                       outSISIDXREG(SISCR, 0x86, 0x00);
+                       inSISIDXREG(SISCR, 0x86, reg);
+                       outSISIDXREG(SISCR, 0x86, 0x88);
+                       inSISIDXREG(SISCR, 0x86, reg);
+                       outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+                       outSISIDXREG(SISCR, 0x82, 0x77);
+                       outSISIDXREG(SISCR, 0x85, 0x00);
+                       inSISIDXREG(SISCR, 0x85, reg);
+                       outSISIDXREG(SISCR, 0x85, 0x88);
+                       inSISIDXREG(SISCR, 0x85, reg);
+                       outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
+                       outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+               }
+               if(ivideo->chip == XGI_40) {
+                       outSISIDXREG(SISCR, 0x97, 0x00);
+               }
+               outSISIDXREG(SISCR, 0x98, 0x01);
+               outSISIDXREG(SISCR, 0x9a, 0x02);
 
-       outSISIDXREG(SISSR,0x20,0x20);
+               outSISIDXREG(SISSR, 0x18, 0x01);
+               if((ivideo->chip == XGI_20) ||
+                  (ivideo->revision_id == 2)) {
+                       outSISIDXREG(SISSR, 0x19, 0x40);
+               } else {
+                       outSISIDXREG(SISSR, 0x19, 0x20);
+               }
+               outSISIDXREG(SISSR, 0x16, 0x00);
+               outSISIDXREG(SISSR, 0x16, 0x80);
+               if((ivideo->chip == XGI_20) || (bios[0x1cb] != 0x0c)) {
+                       sisfb_post_xgi_delay(ivideo, 0x43);
+                       sisfb_post_xgi_delay(ivideo, 0x43);
+                       sisfb_post_xgi_delay(ivideo, 0x43);
+                       outSISIDXREG(SISSR, 0x18, 0x00);
+                       if((ivideo->chip == XGI_20) ||
+                          (ivideo->revision_id == 2)) {
+                               outSISIDXREG(SISSR, 0x19, 0x40);
+                       } else {
+                               outSISIDXREG(SISSR, 0x19, 0x20);
+                       }
+               } else if((ivideo->chip == XGI_40) && (bios[0x1cb] == 0x0c)) {
+                       /* outSISIDXREG(SISSR, 0x16, 0x0c); */ /* ? */
+               }
+               outSISIDXREG(SISSR, 0x16, 0x00);
+               outSISIDXREG(SISSR, 0x16, 0x80);
+               sisfb_post_xgi_delay(ivideo, 4);
+               v1 = 0x31; v2 = 0x03; v3 = 0x83; v4 = 0x03; v5 = 0x83;
+               if(ivideo->haveXGIROM) {
+                       v1 = bios[0xf0];
+                       index = (ivideo->chip == XGI_20) ? 0x4b2 : 0x53e;
+                       v2 = bios[index];
+                       v3 = bios[index + 1];
+                       v4 = bios[index + 2];
+                       v5 = bios[index + 3];
+               }
+               outSISIDXREG(SISSR, 0x18, v1);
+               outSISIDXREG(SISSR, 0x19, ((ivideo->chip == XGI_20) ? 0x02 : 0x01));
+               outSISIDXREG(SISSR, 0x16, v2);
+               outSISIDXREG(SISSR, 0x16, v3);
+               sisfb_post_xgi_delay(ivideo, 0x43);
+               outSISIDXREG(SISSR, 0x1b, 0x03);
+               sisfb_post_xgi_delay(ivideo, 0x22);
+               outSISIDXREG(SISSR, 0x18, v1);
+               outSISIDXREG(SISSR, 0x19, 0x00);
+               outSISIDXREG(SISSR, 0x16, v4);
+               outSISIDXREG(SISSR, 0x16, v5);
+               outSISIDXREG(SISSR, 0x1b, 0x00);
+               break;
+       case 1:
+               outSISIDXREG(SISCR, 0x82, 0x77);
+               outSISIDXREG(SISCR, 0x86, 0x00);
+               inSISIDXREG(SISCR, 0x86, reg);
+               outSISIDXREG(SISCR, 0x86, 0x88);
+               inSISIDXREG(SISCR, 0x86, reg);
+               v1 = cs168[regb]; v2 = cs160[regb]; v3 = cs158[regb];
+               if(ivideo->haveXGIROM) {
+                       v1 = bios[regb + 0x168];
+                       v2 = bios[regb + 0x160];
+                       v3 = bios[regb + 0x158];
+               }
+               outSISIDXREG(SISCR, 0x86, v1);
+               outSISIDXREG(SISCR, 0x82, 0x77);
+               outSISIDXREG(SISCR, 0x85, 0x00);
+               inSISIDXREG(SISCR, 0x85, reg);
+               outSISIDXREG(SISCR, 0x85, 0x88);
+               inSISIDXREG(SISCR, 0x85, reg);
+               outSISIDXREG(SISCR, 0x85, v2);
+               outSISIDXREG(SISCR, 0x82, v3);
+               outSISIDXREG(SISCR, 0x98, 0x01);
+               outSISIDXREG(SISCR, 0x9a, 0x02);
+
+               outSISIDXREG(SISSR, 0x28, 0x64);
+               outSISIDXREG(SISSR, 0x29, 0x63);
+               sisfb_post_xgi_delay(ivideo, 15);
+               outSISIDXREG(SISSR, 0x18, 0x00);
+               outSISIDXREG(SISSR, 0x19, 0x20);
+               outSISIDXREG(SISSR, 0x16, 0x00);
+               outSISIDXREG(SISSR, 0x16, 0x80);
+               outSISIDXREG(SISSR, 0x18, 0xc5);
+               outSISIDXREG(SISSR, 0x19, 0x23);
+               outSISIDXREG(SISSR, 0x16, 0x00);
+               outSISIDXREG(SISSR, 0x16, 0x80);
+               sisfb_post_xgi_delay(ivideo, 1);
+               outSISIDXREG(SISCR, 0x97,0x11);
+               sisfb_post_xgi_setclocks(ivideo, regb);
+               sisfb_post_xgi_delay(ivideo, 0x46);
+               outSISIDXREG(SISSR, 0x18, 0xc5);
+               outSISIDXREG(SISSR, 0x19, 0x23);
+               outSISIDXREG(SISSR, 0x16, 0x00);
+               outSISIDXREG(SISSR, 0x16, 0x80);
+               sisfb_post_xgi_delay(ivideo, 1);
+               outSISIDXREG(SISSR, 0x1b, 0x04);
+               sisfb_post_xgi_delay(ivideo, 1);
+               outSISIDXREG(SISSR, 0x1b, 0x00);
+               sisfb_post_xgi_delay(ivideo, 1);
+               v1 = 0x31;
+               if(ivideo->haveXGIROM) {
+                       v1 = bios[0xf0];
+               }
+               outSISIDXREG(SISSR, 0x18, v1);
+               outSISIDXREG(SISSR, 0x19, 0x06);
+               outSISIDXREG(SISSR, 0x16, 0x04);
+               outSISIDXREG(SISSR, 0x16, 0x84);
+               sisfb_post_xgi_delay(ivideo, 1);
+               break;
+       default:
+               sisfb_post_xgi_setclocks(ivideo, regb);
+               if((ivideo->chip == XGI_40) &&
+                  ((ivideo->revision_id == 1) ||
+                   (ivideo->revision_id == 2))) {
+                       outSISIDXREG(SISCR, 0x82, bios[regb + 0x158]);
+                       outSISIDXREG(SISCR, 0x85, bios[regb + 0x160]);
+                       outSISIDXREG(SISCR, 0x86, bios[regb + 0x168]);
+               } else {
+                       outSISIDXREG(SISCR, 0x82, 0x88);
+                       outSISIDXREG(SISCR, 0x86, 0x00);
+                       inSISIDXREG(SISCR, 0x86, reg);
+                       outSISIDXREG(SISCR, 0x86, 0x88);
+                       outSISIDXREG(SISCR, 0x82, 0x77);
+                       outSISIDXREG(SISCR, 0x85, 0x00);
+                       inSISIDXREG(SISCR, 0x85, reg);
+                       outSISIDXREG(SISCR, 0x85, 0x88);
+                       inSISIDXREG(SISCR, 0x85, reg);
+                       v1 = cs160[regb]; v2 = cs158[regb];
+                       if(ivideo->haveXGIROM) {
+                               v1 = bios[regb + 0x160];
+                               v2 = bios[regb + 0x158];
+                       }
+                       outSISIDXREG(SISCR, 0x85, v1);
+                       outSISIDXREG(SISCR, 0x82, v2);
+               }
+               if(ivideo->chip == XGI_40) {
+                       outSISIDXREG(SISCR, 0x97, 0x11);
+               }
+               if((ivideo->chip == XGI_40) && (ivideo->revision_id == 2)) {
+                       outSISIDXREG(SISCR, 0x98, 0x01);
+               } else {
+                       outSISIDXREG(SISCR, 0x98, 0x03);
+               }
+               outSISIDXREG(SISCR, 0x9a, 0x02);
 
-       v1 = 0xf6; v2 = 0x0d; v3 = 0x33;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9c];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9d];
-          v3 = ivideo->sishw_ext.pjVirtualRomBase[0x9e];
+               if(ivideo->chip == XGI_40) {
+                       outSISIDXREG(SISSR, 0x18, 0x01);
+               } else {
+                       outSISIDXREG(SISSR, 0x18, 0x00);
+               }
+               outSISIDXREG(SISSR, 0x19, 0x40);
+               outSISIDXREG(SISSR, 0x16, 0x00);
+               outSISIDXREG(SISSR, 0x16, 0x80);
+               if((ivideo->chip == XGI_40) && (bios[0x1cb] != 0x0c)) {
+                       sisfb_post_xgi_delay(ivideo, 0x43);
+                       sisfb_post_xgi_delay(ivideo, 0x43);
+                       sisfb_post_xgi_delay(ivideo, 0x43);
+                       outSISIDXREG(SISSR, 0x18, 0x00);
+                       outSISIDXREG(SISSR, 0x19, 0x40);
+                       outSISIDXREG(SISSR, 0x16, 0x00);
+                       outSISIDXREG(SISSR, 0x16, 0x80);
+               }
+               sisfb_post_xgi_delay(ivideo, 4);
+               v1 = 0x31;
+               if(ivideo->haveXGIROM) {
+                       v1 = bios[0xf0];
+               }
+               outSISIDXREG(SISSR, 0x18, v1);
+               outSISIDXREG(SISSR, 0x19, 0x01);
+               if(ivideo->chip == XGI_40) {
+                       outSISIDXREG(SISSR, 0x16, bios[0x53e]);
+                       outSISIDXREG(SISSR, 0x16, bios[0x53f]);
+               } else {
+                       outSISIDXREG(SISSR, 0x16, 0x05);
+                       outSISIDXREG(SISSR, 0x16, 0x85);
+               }
+               sisfb_post_xgi_delay(ivideo, 0x43);
+               if(ivideo->chip == XGI_40) {
+                       outSISIDXREG(SISSR, 0x1b, 0x01);
+               } else {
+                       outSISIDXREG(SISSR, 0x1b, 0x03);
+               }
+               sisfb_post_xgi_delay(ivideo, 0x22);
+               outSISIDXREG(SISSR, 0x18, v1);
+               outSISIDXREG(SISSR, 0x19, 0x00);
+               if(ivideo->chip == XGI_40) {
+                       outSISIDXREG(SISSR, 0x16, bios[0x540]);
+                       outSISIDXREG(SISSR, 0x16, bios[0x541]);
+               } else {
+                       outSISIDXREG(SISSR, 0x16, 0x05);
+                       outSISIDXREG(SISSR, 0x16, 0x85);
+               }
+               outSISIDXREG(SISSR, 0x1b, 0x00);
        }
-       outSISIDXREG(SISSR,0x23,v1);
-       outSISIDXREG(SISSR,0x24,v2);
-       outSISIDXREG(SISSR,0x25,v3);
 
-       outSISIDXREG(SISSR,0x21,0x84);
-       outSISIDXREG(SISSR,0x22,0x00);
-       outSISIDXREG(SISSR,0x27,0x1f);
-
-       v1 = 0x00; v2 = 0x00;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9F];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[0xA1];
-       }
-       outSISIDXREG(SISSR,0x31,v1);
-       outSISIDXREG(SISSR,0x33,v2);
-
-       v1 = 0x11;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0xA0];
-       }
-       v2 = inSISIDXREG(SISPART4,0x00);
-       if((v2 != 1) && (v2 != 2)) v1 &= 0xef;
-       outSISIDXREG(SISSR,0x32,v1);
-
-       /* AGP */
-       pci_read_config_long(pdev, 0x50, &reg1_32);
-       reg1_32 >>= 20;
-       reg1_32 &= 0x0f;
-       if(reg1_32 == 1) {
-          v1 = 0xAA; v2 = 0x33;
-          if(ivideo->sishw_ext.UseROM) {
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF7];
-             v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9E];
-          }
-       } else {
-          v1 = 0x88; v2 = 0x03;
-          if(ivideo->sishw_ext.UseROM) {
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[0xF8];
-             v2 = ivideo->sishw_ext.pjVirtualRomBase[0xF6];
-          }
+       regb = 0;       /* ! */
+       v1 = 0x03;
+       if(ivideo->haveXGIROM) {
+               v1 = bios[0x110 + regb];
        }
-       outSISIDXREG(SISCR,0x49,v1);
-       outSISIDXREG(SISSR,0x25,v2);
+       outSISIDXREG(SISSR, 0x1b, v1);
 
-       v1 = inSISIDXREG(SISPART4,0x00);
-       if((v1 == 1) || (v1 == 2)) {
-          orSISIDXREG(SISPART1,0x2F,0x01);  /* Unlock CRT2 */
-          outSISIDXREG(SISPART1,0x00,0x00);
-          v1 = 0x00;
-          if(ivideo->sishw_ext.UseROM) {
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb6];
-          }
-          outSISIDXREG(SISPART1,0x02,v1);
-          outSISIDXREG(SISPART1,0x2E,0x08);
-          outSISIDXREG(SISPART2,0x00,0x1c);
-          v1 = 0x40; v2 = 0x00; v3 = 0x80;
-          if(ivideo->sishw_ext.UseROM) {
-             v1 = ivideo->sishw_ext.pjVirtualRomBase[0xb7];
-             v2 = ivideo->sishw_ext.pjVirtualRomBase[0xb8];
-             v3 = ivideo->sishw_ext.pjVirtualRomBase[0xbb];
-          }
-          outSISIDXREG(SISPART4,0x0d,v1);
-          outSISIDXREG(SISPART4,0x0e,v2);
-          outSISIDXREG(SISPART4,0x10,v3);
-          outSISIDXREG(SISPART4,0x0F,0x3F);
-
-          inSISIDXREG(SISPART4,0x01,reg);
-          if(reg >= 0xb0) {
-             inSISIDXREG(SISPART4,0x23,reg);
-             reg &= 0x20;
-             reg <<= 1;
-             outSISIDXREG(SISPART4,0x23,reg);
-          }
+       /* RAM size */
+       v1 = 0x00; v2 = 0x00;
+       if(ivideo->haveXGIROM) {
+               v1 = bios[0x62];
+               v2 = bios[0x63];
        }
-       outSISIDXREG(SISCR,0x37,0x02); /* Why? */
-
-       outSISIDXREG(SISCR,0x83,0x00);
-       outSISIDXREG(SISCR,0x90,0x00);
-       andSISIDXREG(SISSR,0x5B,0xDF);
-       outSISIDXREG(SISVID,0x00,0x86);
-       outSISIDXREG(SISVID,0x32,0x00);
-       outSISIDXREG(SISVID,0x30,0x00);
-       outSISIDXREG(SISVID,0x32,0x01);
-       outSISIDXREG(SISVID,0x30,0x00);
-       orSISIDXREG(SISCR,0x63,0x80);
-       /* End of Init1 */
-
-       /* Set Mode 0x2e */
-
-       /* Ramsize */
-       orSISIDXREG(SISSR,0x16,0x0f);
-       orSISIDXREG(SISSR,0x18,0xA9);
-       orSISIDXREG(SISSR,0x19,0xA0);
-       orSISIDXREG(SISSR,0x1B,0x30);
-       andSISIDXREG(SISSR,0x17,0xF8);
-       orSISIDXREG(SISSR,0x19,0x03);
-       andSIDIDXREG(SISSR,0x13,0x00);
+       regb = 0;       /* ! */
+       regd = 1 << regb;
+       if((v1 & 0x40) && (v2 & regd) && ivideo->haveXGIROM) {
 
-       /* Need to map max FB size for finding out about RAM size */
-       ivideo->video_vbase = ioremap(ivideo->video_base, 0x4000000);
-       if(ivideo->video_vbase) {
-          /* Find out about bus width */
-          if(memtype <= 1) {
-             outSISIDXREG(SISSR,0x14,0x02);
-             andSISIDXREG(SISSR,0x16,0x0F);
-             orSISIDXREG(SISSR,0x16,0x80);
+               outSISIDXREG(SISSR, 0x13, bios[regb + 0xe0]);
+               outSISIDXREG(SISSR, 0x14, bios[regb + 0xe0 + 8]);
 
-             ...
+       } else {
 
-          } else {
+               /* Set default mode, don't clear screen */
+               ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+               SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+               SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+               ivideo->curFSTN = ivideo->curDSTN = 0;
+               ivideo->SiS_Pr.VideoMemorySize = 8 << 20;
+               SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
 
-             ...
+               outSISIDXREG(SISSR, 0x05, 0x86);
 
-          }
+               /* Disable read-cache */
+               andSISIDXREG(SISSR, 0x21, 0xdf);
+               sisfb_post_xgi_ramsize(ivideo);
+               /* Enable read-cache */
+               orSISIDXREG(SISSR, 0x21, 0x20);
 
-          /* Find out about size */
+       }
 
+#if 0
+       printk(KERN_DEBUG "-----------------\n");
+       for(i = 0; i < 0xff; i++) {
+               inSISIDXREG(SISCR, i, reg);
+               printk(KERN_DEBUG "CR%02x(%x) = 0x%02x\n", i, SISCR, reg);
+       }
+       for(i = 0; i < 0x40; i++) {
+               inSISIDXREG(SISSR, i, reg);
+               printk(KERN_DEBUG "SR%02x(%x) = 0x%02x\n", i, SISSR, reg);
+       }
+       printk(KERN_DEBUG "-----------------\n");
+#endif
 
-          iounmap(ivideo->video_vbase);
+       /* Sense CRT1 */
+       if(ivideo->chip == XGI_20) {
+               orSISIDXREG(SISCR, 0x32, 0x20);
        } else {
-          printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
-          outSISIDXREG(SISSR,0x14,0x??);  /* 8MB, 64bit default */
+               inSISIDXREG(SISPART4, 0x00, reg);
+               if((reg == 1) || (reg == 2)) {
+                       sisfb_sense_crt1(ivideo);
+               } else {
+                       orSISIDXREG(SISCR, 0x32, 0x20);
+               }
        }
 
-       /* AGP (Missing: Checks for VIA and AMD hosts) */
-       v1 = 0xA5; v2 = 0xFB;
-       if(ivideo->sishw_ext.UseROM) {
-          v1 = ivideo->sishw_ext.pjVirtualRomBase[0x9A];
-          v2 = ivideo->sishw_ext.pjVirtualRomBase[0x9B];
+       /* Set default mode, don't clear screen */
+       ivideo->SiS_Pr.SiS_UseOEM = FALSE;
+       SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+       SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
+       ivideo->curFSTN = ivideo->curDSTN = 0;
+       SiSSetMode(&ivideo->SiS_Pr, 0x2e | 0x80);
+
+       outSISIDXREG(SISSR, 0x05, 0x86);
+
+       /* Display off */
+       orSISIDXREG(SISSR, 0x01, 0x20);
+
+       /* Save mode number in CR34 */
+       outSISIDXREG(SISCR, 0x34, 0x2e);
+
+       /* Let everyone know what the current mode is */
+       ivideo->modeprechange = 0x2e;
+
+       if(ivideo->chip == XGI_40) {
+               inSISIDXREG(SISCR, 0xca, reg);
+               inSISIDXREG(SISCR, 0xcc, v1);
+               if((reg & 0x10) && (!(v1 & 0x04))) {
+                       printk(KERN_ERR
+                               "sisfb: Please connect power to the card.\n");
+                       return 0;
+               }
        }
-       outSISIDXREG(SISSR,0x21,v1);
-       outSISIDXREG(SISSR,0x22,v2);
 
-#endif
-       return;
+       return 1;
 }
 #endif
 
-
-static int __devinit sisfb_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int __devinit
+sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       struct sisfb_chip_info  *chipinfo = &sisfb_chip_info[ent->driver_data];
-       struct sis_video_info   *ivideo = NULL;
-       struct fb_info          *sis_fb_info = NULL;
+       struct sisfb_chip_info  *chipinfo = &sisfb_chip_info[ent->driver_data];
+       struct sis_video_info   *ivideo = NULL;
+       struct fb_info          *sis_fb_info = NULL;
        u16 reg16;
        u8  reg;
-       int sisvga_enabled = 0, i;
+       int i, ret;
 
-       if(sisfb_off) return -ENXIO;
+       if(sisfb_off)
+               return -ENXIO;
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
        sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
-       if(!sis_fb_info) return -ENOMEM;
+       if(!sis_fb_info)
+               return -ENOMEM;
 #else
        sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
-       if(!sis_fb_info) return -ENOMEM;
+       if(!sis_fb_info)
+               return -ENOMEM;
        memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
        sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
 #endif
@@ -4787,27 +5890,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
        ivideo = (struct sis_video_info *)sis_fb_info->par;
        ivideo->memyselfandi = sis_fb_info;
 
+       ivideo->sisfb_id = SISFB_ID;
+
        if(card_list == NULL) {
-          ivideo->cardnumber = 0;
+               ivideo->cardnumber = 0;
        } else {
-          struct sis_video_info *countvideo = card_list;
-          ivideo->cardnumber = 1;
-          while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++;
+               struct sis_video_info *countvideo = card_list;
+               ivideo->cardnumber = 1;
+               while((countvideo = countvideo->next) != 0)
+                       ivideo->cardnumber++;
        }
 
        strncpy(ivideo->myid, chipinfo->chip_name, 30);
 
        ivideo->warncount = 0;
        ivideo->chip_id = pdev->device;
+       ivideo->chip_vendor = pdev->vendor;
        pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
-       ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
+       ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
        pci_read_config_word(pdev, PCI_COMMAND, &reg16);
-       sisvga_enabled = reg16 & 0x01;
+       ivideo->sisvga_enabled = reg16 & 0x01;
        ivideo->pcibus = pdev->bus->number;
        ivideo->pcislot = PCI_SLOT(pdev->devfn);
        ivideo->pcifunc = PCI_FUNC(pdev->devfn);
        ivideo->subsysvendor = pdev->subsystem_vendor;
        ivideo->subsysdevice = pdev->subsystem_device;
+#ifdef SIS_OLD_CONFIG_COMPAT
+       ivideo->ioctl32registered = 0;
+#endif
 
 #ifndef MODULE
        if(sisfb_mode_idx == -1) {
@@ -4827,6 +5937,24 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 
        ivideo->sisfb_thismonitor.datavalid = FALSE;
 
+       ivideo->current_base = 0;
+
+       ivideo->engineok = 0;
+
+       ivideo->sisfb_was_boot_device = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+       if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
+               if(ivideo->sisvga_enabled)
+                       ivideo->sisfb_was_boot_device = 1;
+               else {
+                       printk(KERN_DEBUG "sisfb: PCI device is disabled, "
+                               "but marked as boot video device ???\n");
+                       printk(KERN_DEBUG "sisfb: I will not accept this "
+                               "as the primary VGA device\n");
+               }
+       }
+#endif
+
        ivideo->sisfb_parm_mem = sisfb_parm_mem;
        ivideo->sisfb_accel = sisfb_accel;
        ivideo->sisfb_ypan = sisfb_ypan;
@@ -4846,7 +5974,6 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
        ivideo->sisfb_tvstd = sisfb_tvstd;
        ivideo->tvxpos = sisfb_tvxposoffset;
        ivideo->tvypos = sisfb_tvyposoffset;
-       ivideo->sisfb_filter = sisfb_filter;
        ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
        ivideo->sisfb_inverse = sisfb_inverse;
@@ -4854,7 +5981,7 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 
        ivideo->refresh_rate = 0;
        if(ivideo->sisfb_parm_rate != -1) {
-          ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+               ivideo->refresh_rate = ivideo->sisfb_parm_rate;
        }
 
        ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
@@ -4863,8 +5990,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
        ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
 
        ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
-        ivideo->SiS_Pr.SiS_CHOverScan = -1;
-        ivideo->SiS_Pr.SiS_ChSW = FALSE;
+       ivideo->SiS_Pr.SiS_CHOverScan = -1;
+       ivideo->SiS_Pr.SiS_ChSW = FALSE;
        ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
        ivideo->SiS_Pr.HaveEMI = FALSE;
        ivideo->SiS_Pr.HaveEMILCD = FALSE;
@@ -4873,12 +6000,13 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
        ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
        ivideo->SiS_Pr.PDC  = -1;
        ivideo->SiS_Pr.PDCA = -1;
+       ivideo->SiS_Pr.DDCPortMixup = FALSE;
 #ifdef CONFIG_FB_SIS_315
        if(ivideo->chip >= SIS_330) {
-          ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
-          if(ivideo->chip >= SIS_661) {
-             ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
-          }
+               ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+               if(ivideo->chip >= SIS_661) {
+                       ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+               }
        }
 #endif
 
@@ -4891,9 +6019,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                switch(ivideo->nbridge->device) {
 #ifdef CONFIG_FB_SIS_300
                case PCI_DEVICE_ID_SI_730:
-                       ivideo->chip = SIS_730;
+                       ivideo->chip = SIS_730;
                        strcpy(ivideo->myid, "SiS 730");
-                       break;
+                       break;
 #endif
 #ifdef CONFIG_FB_SIS_315
                case PCI_DEVICE_ID_SI_651:
@@ -4901,22 +6029,28 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                        strcpy(ivideo->myid, "SiS 651");
                        break;
                case PCI_DEVICE_ID_SI_740:
-                       ivideo->chip = SIS_740;
+                       ivideo->chip = SIS_740;
                        strcpy(ivideo->myid, "SiS 740");
                        break;
                case PCI_DEVICE_ID_SI_661:
-                       ivideo->chip = SIS_661;
+                       ivideo->chip = SIS_661;
                        strcpy(ivideo->myid, "SiS 661");
                        break;
                case PCI_DEVICE_ID_SI_741:
-                       ivideo->chip = SIS_741;
+                       ivideo->chip = SIS_741;
                        strcpy(ivideo->myid, "SiS 741");
                        break;
                case PCI_DEVICE_ID_SI_760:
-                       ivideo->chip = SIS_760;
+                       ivideo->chip = SIS_760;
                        strcpy(ivideo->myid, "SiS 760");
                        break;
+               case PCI_DEVICE_ID_SI_761:
+                       ivideo->chip = SIS_761;
+                       strcpy(ivideo->myid, "SiS 761");
+                       break;
 #endif
+               default:
+                       break;
                }
        }
 
@@ -4924,71 +6058,83 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
        strcpy(sis_fb_info->modename, ivideo->myid);
 #endif
 
-       ivideo->sishw_ext.jChipType = ivideo->chip;
+       ivideo->SiS_Pr.ChipType = ivideo->chip;
+
+       ivideo->SiS_Pr.ivideo = (void *)ivideo;
 
 #ifdef CONFIG_FB_SIS_315
-       if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
-          (ivideo->sishw_ext.jChipType == SIS_315)) {
-               ivideo->sishw_ext.jChipType = SIS_315H;
+       if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
+          (ivideo->SiS_Pr.ChipType == SIS_315)) {
+               ivideo->SiS_Pr.ChipType = SIS_315H;
        }
 #endif
 
+       if(!ivideo->sisvga_enabled) {
+               if(pci_enable_device(pdev)) {
+                       if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+                       pci_set_drvdata(pdev, NULL);
+                       kfree(sis_fb_info);
+                       return -EIO;
+               }
+       }
+
        ivideo->video_base = pci_resource_start(pdev, 0);
        ivideo->mmio_base  = pci_resource_start(pdev, 1);
        ivideo->mmio_size  = pci_resource_len(pdev, 1);
-       ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
-       ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
-
-       if(!sisvga_enabled) {
-               if(pci_enable_device(pdev)) {
-                       pci_set_drvdata(pdev, NULL);
-                       kfree(sis_fb_info);
-                       return -EIO;
-               }
-       }
+       ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+       ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
 
-       SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
+       SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);
 
 #ifdef CONFIG_FB_SIS_300
        /* Find PCI systems for Chrontel/GPIO communication setup */
        if(ivideo->chip == SIS_630) {
-          i=0;
-           do {
-             if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
-                mychswtable[i].subsysCard   == ivideo->subsysdevice) {
-                ivideo->SiS_Pr.SiS_ChSW = TRUE;
-                printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
-                       mychswtable[i].vendorName, mychswtable[i].cardName);
-                break;
-              }
-              i++;
-           } while(mychswtable[i].subsysVendor != 0);
+               i = 0;
+               do {
+                       if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+                          mychswtable[i].subsysCard   == ivideo->subsysdevice) {
+                               ivideo->SiS_Pr.SiS_ChSW = TRUE;
+                               printk(KERN_DEBUG "sisfb: Identified [%s %s] "
+                                       "requiring Chrontel/GPIO setup\n",
+                                       mychswtable[i].vendorName,
+                                       mychswtable[i].cardName);
+                               ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
+                               break;
+                       }
+                       i++;
+               } while(mychswtable[i].subsysVendor != 0);
+       }
+#endif
+
+#ifdef CONFIG_FB_SIS_315
+       if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
+               ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
        }
 #endif
 
-        outSISIDXREG(SISSR, 0x05, 0x86);
+       outSISIDXREG(SISSR, 0x05, 0x86);
 
-       if( (!sisvga_enabled)
+       if( (!ivideo->sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
-                             || (sisfb_resetcard)
+                             || (sisfb_resetcard)
 #endif
-                                                  ) {
-               for(i = 0x30; i <= 0x3f; i++) {
-                       outSISIDXREG(SISCR,i,0x00);
-               }
+                                                  ) {
+               for(i = 0x30; i <= 0x3f; i++) {
+                       outSISIDXREG(SISCR, i, 0x00);
+               }
        }
 
        /* Find out about current video mode */
        ivideo->modeprechange = 0x03;
-       inSISIDXREG(SISCR,0x34,reg);
+       inSISIDXREG(SISCR, 0x34, reg);
        if(reg & 0x7f) {
                ivideo->modeprechange = reg & 0x7f;
-       } else if(sisvga_enabled) {
+       } else if(ivideo->sisvga_enabled) {
 #if defined(__i386__) || defined(__x86_64__)
-               unsigned char SIS_IOTYPE2 *tt = ioremap(0, 0x1000);
+               unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
                if(tt) {
-                       ivideo->modeprechange = readb(tt + 0x449);
-                       iounmap(tt);
+                       ivideo->modeprechange = readb(tt + 0x49);
+                       iounmap(tt);
                }
 #endif
        }
@@ -4996,219 +6142,221 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #ifdef MODULE
        if((reg & 0x80) && (reg != 0xff)) {
-          if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
-             printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
-             pci_set_drvdata(pdev, NULL);
-             kfree(sis_fb_info);
-             return -EBUSY;
-          }
+               if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni])
+                                                                       != 0xFF) {
+                       printk(KERN_INFO "sisfb: Cannot initialize display mode, "
+                                        "X server is active\n");
+                       ret = -EBUSY;
+                       goto error_4;
+               }
        }
-#endif 
 #endif
-
-       ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
-#ifdef CONFIG_FB_SIS_300
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-          if(ivideo->chip != SIS_300) {
-             inSISIDXREG(SISSR, 0x1a, reg);
-             if(!(reg & 0x10)) {
-                ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
-             }
-          }
-       }
 #endif
 
+       /* Search and copy ROM image */
        ivideo->bios_abase = NULL;
+       ivideo->SiS_Pr.VirtualRomBase = NULL;
+       ivideo->SiS_Pr.UseROM = FALSE;
+       ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
        if(ivideo->sisfb_userom) {
-           ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
-           ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;
-           if(ivideo->sishw_ext.pjVirtualRomBase) {
-               printk(KERN_INFO "sisfb: Video ROM found and copied\n");
-               ivideo->sishw_ext.UseROM = TRUE;
-           } else {
-               ivideo->sishw_ext.UseROM = FALSE;
-               printk(KERN_INFO "sisfb: Video ROM not found\n");
-           }
+               ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
+               ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
+               ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
+               printk(KERN_INFO "sisfb: Video ROM %sfound\n",
+                       ivideo->SiS_Pr.UseROM ? "" : "not ");
+               if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
+                  ivideo->SiS_Pr.UseROM = FALSE;
+                  ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
+                  if( (ivideo->revision_id == 2) &&
+                      (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
+                       ivideo->SiS_Pr.DDCPortMixup = TRUE;
+                  }
+               }
        } else {
-           ivideo->sishw_ext.pjVirtualRomBase = NULL;
-           ivideo->sishw_ext.UseROM = FALSE;
-           printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
+               printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
        }
 
-        /* Find systems for special custom timing */
+       /* Find systems for special custom timing */
        if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
-          int j;
-          unsigned char *biosver = NULL;
-           unsigned char *biosdate = NULL;
-          BOOLEAN footprint;
-          u32 chksum = 0;
-
-          if(ivideo->sishw_ext.UseROM) {
-             biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
-             biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
-              for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
-          }
-
-          i=0;
-           do {
-             if( (mycustomttable[i].chipID == ivideo->chip) &&
-                 ((!strlen(mycustomttable[i].biosversion)) ||
-                  (ivideo->sishw_ext.UseROM &&
-                  (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
-                 ((!strlen(mycustomttable[i].biosdate)) ||
-                  (ivideo->sishw_ext.UseROM &&
-                  (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
-                 ((!mycustomttable[i].bioschksum) ||
-                  (ivideo->sishw_ext.UseROM &&
-                  (mycustomttable[i].bioschksum == chksum)))   &&
-                 (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
-                 (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
-                footprint = TRUE;
-                for(j = 0; j < 5; j++) {
-                   if(mycustomttable[i].biosFootprintAddr[j]) {
-                      if(ivideo->sishw_ext.UseROM) {
-                         if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
-                               mycustomttable[i].biosFootprintData[j]) {
-                            footprint = FALSE;
-                         }
-                      } else footprint = FALSE;
-                   }
-                }
-                if(footprint) {
-                   ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
-                   printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
-                       mycustomttable[i].vendorName,
-                       mycustomttable[i].cardName);
-                   printk(KERN_DEBUG "sisfb: [specialtiming parameter name: %s]\n",
-                       mycustomttable[i].optionName);
-                   break;
-                 }
-             }
-              i++;
-           } while(mycustomttable[i].chipID);
+               sisfb_detect_custom_timing(ivideo);
        }
 
-#ifdef CONFIG_FB_SIS_300
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-               if( (!sisvga_enabled)
+       /* POST card in case this has not been done by the BIOS */
+       if( (!ivideo->sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
-                                     || (sisfb_resetcard)
+                            || (sisfb_resetcard)
 #endif
-                                                          ) {
+                                                ) {
+#ifdef CONFIG_FB_SIS_300
+               if(ivideo->sisvga_engine == SIS_300_VGA) {
                        if(ivideo->chip == SIS_300) {
                                sisfb_post_sis300(pdev);
+                               ivideo->sisfb_can_post = 1;
                        }
                }
-       }
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-       if(ivideo->sisvga_engine == SIS_315_VGA) {
-               if( (!sisvga_enabled)
-#if !defined(__i386__) && !defined(__x86_64__)
-                                    || (sisfb_resetcard)
-#endif
-                                                         ) {
-                       if((ivideo->chip == SIS_315H)   ||
+               if(ivideo->sisvga_engine == SIS_315_VGA) {
+                       int result = 1;
+               /*      if((ivideo->chip == SIS_315H)   ||
                           (ivideo->chip == SIS_315)    ||
                           (ivideo->chip == SIS_315PRO) ||
                           (ivideo->chip == SIS_330)) {
                                sisfb_post_sis315330(pdev);
+                       } else */ if(ivideo->chip == XGI_20) {
+                               result = sisfb_post_xgi(pdev);
+                               ivideo->sisfb_can_post = 1;
+                       } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
+                               result = sisfb_post_xgi(pdev);
+                               ivideo->sisfb_can_post = 1;
+                       } else {
+                               printk(KERN_INFO "sisfb: Card is not "
+                                       "POSTed and sisfb can't do this either.\n");
+                       }
+                       if(!result) {
+                               printk(KERN_ERR "sisfb: Failed to POST card\n");
+                               ret = -ENODEV;
+                               goto error_3;
                        }
                }
-       }
 #endif
+       }
 
+       ivideo->sisfb_card_posted = 1;
+
+       /* Find out about RAM size */
        if(sisfb_get_dram_size(ivideo)) {
-               printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
-               if(ivideo->bios_abase) vfree(ivideo->bios_abase);
-               pci_set_drvdata(pdev, NULL);
-               kfree(sis_fb_info);
-               return -ENODEV;
+               printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
+               ret = -ENODEV;
+               goto error_3;
        }
 
+
+       /* Enable PCI addressing and MMIO */
        if((ivideo->sisfb_mode_idx < 0) ||
           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
-               /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
-               orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
-                /* Enable 2D accelerator engine */
-               orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
+               /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
+               orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
+               /* Enable 2D accelerator engine */
+               orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
        }
 
        if(sisfb_pdc != 0xff) {
-          if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
-          else                                     sisfb_pdc &= 0x1f;
-          ivideo->SiS_Pr.PDC = sisfb_pdc;
+               if(ivideo->sisvga_engine == SIS_300_VGA)
+                       sisfb_pdc &= 0x3c;
+               else
+                       sisfb_pdc &= 0x1f;
+               ivideo->SiS_Pr.PDC = sisfb_pdc;
        }
 #ifdef CONFIG_FB_SIS_315
        if(ivideo->sisvga_engine == SIS_315_VGA) {
-          if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
+               if(sisfb_pdca != 0xff)
+                       ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
        }
 #endif
 
        if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
-               printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
+               printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
+                               (int)(ivideo->video_size >> 20));
                printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
-               if(ivideo->bios_abase) vfree(ivideo->bios_abase);
-               pci_set_drvdata(pdev, NULL);
-               kfree(sis_fb_info);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto error_3;
        }
 
        if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
                printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
-               release_mem_region(ivideo->video_base, ivideo->video_size);
-               if(ivideo->bios_abase) vfree(ivideo->bios_abase);
-               pci_set_drvdata(pdev, NULL);
-               kfree(sis_fb_info);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto error_2;
        }
 
        ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
-       ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase;
+       ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
        if(!ivideo->video_vbase) {
-               printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
-               release_mem_region(ivideo->video_base, ivideo->video_size);
-               release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
-               if(ivideo->bios_abase) vfree(ivideo->bios_abase);
-               pci_set_drvdata(pdev, NULL);
-               kfree(sis_fb_info);
-               return -ENODEV;
+               printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
+               ret = -ENODEV;
+               goto error_1;
        }
 
        ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
        if(!ivideo->mmio_vbase) {
-               printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-               iounmap(ivideo->video_vbase);
-               release_mem_region(ivideo->video_base, ivideo->video_size);
-               release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
-               if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+               printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
+               ret = -ENODEV;
+error_0:       iounmap(ivideo->video_vbase);
+error_1:       release_mem_region(ivideo->video_base, ivideo->video_size);
+error_2:       release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+error_3:       vfree(ivideo->bios_abase);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+error_4:
+#endif
+               if(ivideo->lpcdev)
+                       SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+               if(ivideo->nbridge)
+                       SIS_PCI_PUT_DEVICE(ivideo->nbridge);
                pci_set_drvdata(pdev, NULL);
-               kfree(sis_fb_info);
-               return -ENODEV;
+               if(!ivideo->sisvga_enabled)
+                       pci_disable_device(pdev);
+               kfree(sis_fb_info);
+               return ret;
        }
 
-       printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
-               ivideo->video_base, (ULONG)ivideo->video_vbase, ivideo->video_size / 1024);
+       printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
+               ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);
+
+       if(ivideo->video_offset) {
+               printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
+                       ivideo->video_offset / 1024);
+       }
 
        printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
-               ivideo->mmio_base, (ULONG)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+               ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+
+
+       /* Determine the size of the command queue */
+       if(ivideo->sisvga_engine == SIS_300_VGA) {
+               ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
+       } else {
+               if(ivideo->chip == XGI_20) {
+                       ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
+               } else {
+                       ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
+               }
+       }
 
+       /* Engines are no longer initialized here; this is
+        * now done after the first mode-switch (if the
+        * submitted var has its acceleration flags set).
+        */
+
+       /* Calculate the base of the (unused) hw cursor */
+       ivideo->hwcursor_vbase = ivideo->video_vbase
+                                + ivideo->video_size
+                                - ivideo->cmdQueueSize
+                                - ivideo->hwcursor_size;
+       ivideo->caps |= HW_CURSOR_CAP;
+
+       /* Initialize offscreen memory manager */
        if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
                printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
        }
 
        /* Used for clearing the screen only, therefore respect our mem limit */
-       ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
+       ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
+       ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;
 
-       ivideo->mtrr = 0;
+       ivideo->mtrr = -1;
 
        ivideo->vbflags = 0;
        ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
        ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
        ivideo->defmodeidx    = DEFAULT_MODE;
 
-       ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
+       ivideo->newrom = 0;
+       if(ivideo->chip < XGI_20) {
+               if(ivideo->bios_abase) {
+                       ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
+               }
+       }
 
        if((ivideo->sisfb_mode_idx < 0) ||
           ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
@@ -5217,192 +6365,57 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 
                sisfb_get_VB_type(ivideo);
 
-               if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+               if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
                        sisfb_detect_VB_connect(ivideo);
                }
 
                ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
 
-               if(ivideo->vbflags & VB_VIDEOBRIDGE) {
-                  if(ivideo->sisfb_crt2type != -1) {
-                     if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
-                        ivideo->currentvbflags |= CRT2_LCD;
-                     } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
-                        ivideo->currentvbflags |= ivideo->sisfb_crt2type;
-                     }
-                  } else {
-                     /* Chrontel 700x TV detection often unreliable, therefore use a
-                      * different default order on such machines
-                      */
-                     if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) {
-                        if(ivideo->vbflags & CRT2_LCD)      ivideo->currentvbflags |= CRT2_LCD;
-                        else if(ivideo->vbflags & CRT2_TV)  ivideo->currentvbflags |= CRT2_TV;
-                        else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
-                     } else {
-                        if(ivideo->vbflags & CRT2_TV)       ivideo->currentvbflags |= CRT2_TV;
-                        else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
-                        else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
-                     }
-                  }
+               /* Decide on which CRT2 device to use */
+               if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
+                       if(ivideo->sisfb_crt2type != -1) {
+                               if((ivideo->sisfb_crt2type == CRT2_LCD) &&
+                                  (ivideo->vbflags & CRT2_LCD)) {
+                                       ivideo->currentvbflags |= CRT2_LCD;
+                               } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+                                       ivideo->currentvbflags |= ivideo->sisfb_crt2type;
+                               }
+                       } else {
+                               /* Chrontel 700x TV detection often unreliable, therefore
+                                * use a different default order on such machines
+                                */
+                               if((ivideo->sisvga_engine == SIS_300_VGA) &&
+                                  (ivideo->vbflags2 & VB2_CHRONTEL)) {
+                                       if(ivideo->vbflags & CRT2_LCD)
+                                               ivideo->currentvbflags |= CRT2_LCD;
+                                       else if(ivideo->vbflags & CRT2_TV)
+                                               ivideo->currentvbflags |= CRT2_TV;
+                                       else if(ivideo->vbflags & CRT2_VGA)
+                                               ivideo->currentvbflags |= CRT2_VGA;
+                               } else {
+                                       if(ivideo->vbflags & CRT2_TV)
+                                               ivideo->currentvbflags |= CRT2_TV;
+                                       else if(ivideo->vbflags & CRT2_LCD)
+                                               ivideo->currentvbflags |= CRT2_LCD;
+                                       else if(ivideo->vbflags & CRT2_VGA)
+                                               ivideo->currentvbflags |= CRT2_VGA;
+                               }
+                       }
                }
 
                if(ivideo->vbflags & CRT2_LCD) {
-                  inSISIDXREG(SISCR, 0x36, reg);
-                  reg &= 0x0f;
-                  if(ivideo->sisvga_engine == SIS_300_VGA) {
-                     ivideo->CRT2LCDType = sis300paneltype[reg];
-                  } else if(ivideo->chip >= SIS_661) {
-                     ivideo->CRT2LCDType = sis661paneltype[reg];
-                  } else {
-                     ivideo->CRT2LCDType = sis310paneltype[reg];
-                     if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
-                        if((ivideo->CRT2LCDType != LCD_640x480_2) &&
-                           (ivideo->CRT2LCDType != LCD_640x480_3)) {
-                           ivideo->CRT2LCDType = LCD_320x480;
-                        }
-                     }
-                  }
-                  if(ivideo->CRT2LCDType == LCD_UNKNOWN) {
-                     /* For broken BIOSes: Assume 1024x768, RGB18 */
-                     ivideo->CRT2LCDType = LCD_1024x768;
-                     setSISIDXREG(SISCR,0x36,0xf0,0x02);
-                     setSISIDXREG(SISCR,0x37,0xee,0x01);
-                     printk(KERN_DEBUG "sisfb: Invalid panel ID (%02x), assuming 1024x768, RGB18\n", reg);
-                  }
-                  for(i = 0; i < SIS_LCD_NUMBER; i++) {
-                     if(ivideo->CRT2LCDType == sis_lcd_data[i].lcdtype) {
-                        ivideo->lcdxres = sis_lcd_data[i].xres;
-                        ivideo->lcdyres = sis_lcd_data[i].yres;
-                        ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
-                        break;
-                     }
-                  }
-                  if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
-                       ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
-                  } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
-                       ivideo->lcdxres =  848; ivideo->lcdyres =  480; ivideo->lcddefmodeidx = 47;
-                  }
-                  printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n",
-                               ivideo->lcdxres, ivideo->lcdyres);
-               }
-
-#ifdef CONFIG_FB_SIS_300
-                /* Save the current PanelDelayCompensation if the LCD is currently used */
-               if(ivideo->sisvga_engine == SIS_300_VGA) {
-                  if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
-                      int tmp;
-                      inSISIDXREG(SISCR,0x30,tmp);
-                      if(tmp & 0x20) {
-                         /* Currently on LCD? If yes, read current pdc */
-                         inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
-                         ivideo->detectedpdc &= 0x3c;
-                         if(ivideo->SiS_Pr.PDC == -1) {
-                            /* Let option override detection */
-                            ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
-                         }
-                         printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
-                                ivideo->detectedpdc);
-                      }
-                      if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
-                         printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
-                                ivideo->SiS_Pr.PDC);
-                      }
-                  }
+                       sisfb_detect_lcd_type(ivideo);
                }
-#endif
-
-#ifdef CONFIG_FB_SIS_315
-               if(ivideo->sisvga_engine == SIS_315_VGA) {
-
-                  /* Try to find about LCDA */
-                  if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
-                     int tmp;
-                     inSISIDXREG(SISPART1,0x13,tmp);
-                     if(tmp & 0x04) {
-                        ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
-                        ivideo->detectedlcda = 0x03;
-                     }
-                  }
-
-                  /* Save PDC */
-                  if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
-                     int tmp;
-                     inSISIDXREG(SISCR,0x30,tmp);
-                     if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
-                        /* Currently on LCD? If yes, read current pdc */
-                        u8 pdc;
-                        inSISIDXREG(SISPART1,0x2D,pdc);
-                        ivideo->detectedpdc  = (pdc & 0x0f) << 1;
-                        ivideo->detectedpdca = (pdc & 0xf0) >> 3;
-                        inSISIDXREG(SISPART1,0x35,pdc);
-                        ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
-                        inSISIDXREG(SISPART1,0x20,pdc);
-                        ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
-                        if(ivideo->newrom) {
-                           /* New ROM invalidates other PDC resp. */
-                           if(ivideo->detectedlcda != 0xff) {
-                              ivideo->detectedpdc = 0xff;
-                           } else {
-                              ivideo->detectedpdca = 0xff;
-                           }
-                        }
-                        if(ivideo->SiS_Pr.PDC == -1) {
-                           if(ivideo->detectedpdc != 0xff) {
-                              ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
-                           }
-                        }
-                        if(ivideo->SiS_Pr.PDCA == -1) {
-                           if(ivideo->detectedpdca != 0xff) {
-                              ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
-                           }
-                        }
-                        if(ivideo->detectedpdc != 0xff) {
-                           printk(KERN_INFO
-                                "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
-                                 ivideo->detectedpdc);
-                        }
-                        if(ivideo->detectedpdca != 0xff) {
-                           printk(KERN_INFO
-                                "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
-                                 ivideo->detectedpdca);
-                        }
-                     }
-
-                     /* Save EMI */
-                     if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
-                        inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
-                        inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
-                        inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
-                        inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
-                        ivideo->SiS_Pr.HaveEMI = TRUE;
-                        if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
-                               ivideo->SiS_Pr.HaveEMILCD = TRUE;
-                        }
-                     }
-                  }
 
-                  /* Let user override detected PDCs (all bridges) */
-                  if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
-                     if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
-                        printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
-                                ivideo->SiS_Pr.PDC);
-                     }
-                     if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
-                        printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
-                                ivideo->SiS_Pr.PDCA);
-                     }
-                  }
-
-               }
-#endif
+               sisfb_save_pdc_emi(ivideo);
 
                if(!ivideo->sisfb_crt1off) {
-                       sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
+                       sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
                } else {
-                       if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
-                          (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
-                               sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
-                       }
+                       if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
+                          (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+                               sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
+                       }
                }
 
                if(ivideo->sisfb_mode_idx >= 0) {
@@ -5434,7 +6447,8 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 
                if(ivideo->refresh_rate != 0) {
-                       sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
+                       sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
+                                               ivideo->sisfb_mode_idx);
                }
 
                if(ivideo->rate_idx == 0) {
@@ -5443,9 +6457,12 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                }
 
                if(ivideo->sisfb_thismonitor.datavalid) {
-                       if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
-                                             ivideo->rate_idx, ivideo->refresh_rate)) {
-                               printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
+                       if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
+                                               ivideo->sisfb_mode_idx,
+                                               ivideo->rate_idx,
+                                               ivideo->refresh_rate)) {
+                               printk(KERN_INFO "sisfb: WARNING: Refresh rate "
+                                                       "exceeds monitor specs!\n");
                        }
                }
 
@@ -5454,28 +6471,34 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
 
                sisfb_set_vparms(ivideo);
-               
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 
 
-               /* ---------------- For 2.4: Now switch the mode ------------------ */          
-               
-               printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
-                       ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+               /* ---------------- For 2.4: Now switch the mode ------------------ */
+
+               printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
+                       ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
                        ivideo->refresh_rate);
 
+               /* Determine whether or not acceleration is to be
+                * used. Need to know before pre/post_set_mode()
+                */
+               ivideo->accel = 0;
+               ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
+               if(ivideo->sisfb_accel) {
+                       ivideo->accel = -1;
+                       ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+               }
+
+               /* Now switch the mode */
                sisfb_pre_setmode(ivideo);
 
-               if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
+               if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
                        printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
                                                                        ivideo->mode_no);
-                       iounmap(ivideo->video_vbase);
+                       ret = -EINVAL;
                        iounmap(ivideo->mmio_vbase);
-                       release_mem_region(ivideo->video_base, ivideo->video_size);
-                       release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
-                       if(ivideo->bios_abase) vfree(ivideo->bios_abase);
-                       pci_set_drvdata(pdev, NULL);
-                       kfree(sis_fb_info);
-                       return -EINVAL;
+                       goto error_0;
                }
 
                outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
@@ -5488,18 +6511,17 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                /* Force reset of x virtual in crtc_to_var */
                ivideo->default_var.xres_virtual = 0;
 
+               /* Copy mode timing to var */
                sisfb_crtc_to_var(ivideo, &ivideo->default_var);
 
+               /* Find out about screen pitch */
                sisfb_calc_pitch(ivideo, &ivideo->default_var);
                sisfb_set_pitch(ivideo);
 
-               ivideo->accel = 0;
-               if(ivideo->sisfb_accel) {
-                  ivideo->accel = -1;
-                  ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
-               }
+               /* Init the accelerator (does nothing currently) */
                sisfb_initaccel(ivideo);
-               
+
+               /* Init some fbinfo entries */
                sis_fb_info->node  = -1;
                sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
                sis_fb_info->fbops = &sisfb_ops;
@@ -5515,41 +6537,42 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 #else          /* --------- For 2.6: Setup a somewhat sane default var ------------ */
 
                printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
-                       ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+                       ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
                        ivideo->refresh_rate);
 
+               /* Set up the default var according to chosen default display mode */
                ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
                ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
                ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
 
                sisfb_bpp_to_var(ivideo, &ivideo->default_var);
-               
+
                ivideo->default_var.pixclock = (u32) (1000000000 /
-                               sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
-                                               ivideo->mode_no, ivideo->rate_idx));
-                                               
-               if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
-                               ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
-                  if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-                     ivideo->default_var.pixclock <<= 1;
-                  }
-               }
+                       sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));
+
+               if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
+                                               ivideo->rate_idx, &ivideo->default_var)) {
+                       if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+                               ivideo->default_var.pixclock <<= 1;
+                       }
+               }
 
                if(ivideo->sisfb_ypan) {
-                  /* Maximize regardless of sisfb_max at startup */
-                  ivideo->default_var.yres_virtual = sisfb_calc_maxyres(ivideo, &ivideo->default_var);
-                  if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
-                     ivideo->default_var.yres_virtual = ivideo->default_var.yres;
-                  }
+                       /* Maximize regardless of sisfb_max at startup */
+                       ivideo->default_var.yres_virtual =
+                               sisfb_calc_maxyres(ivideo, &ivideo->default_var);
+                       if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
+                               ivideo->default_var.yres_virtual = ivideo->default_var.yres;
+                       }
                }
 
                sisfb_calc_pitch(ivideo, &ivideo->default_var);
 
                ivideo->accel = 0;
                if(ivideo->sisfb_accel) {
-                  ivideo->accel = -1;
+                       ivideo->accel = -1;
 #ifdef STUPID_ACCELF_TEXT_SHIT
-                  ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+                       ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
 #endif
                }
                sisfb_initaccel(ivideo);
@@ -5566,21 +6589,21 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 #endif
                sis_fb_info->var = ivideo->default_var;
                sis_fb_info->fix = ivideo->sisfb_fix;
-               sis_fb_info->screen_base = ivideo->video_vbase;
+               sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
                sis_fb_info->fbops = &sisfb_ops;
 
                sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
                sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
-               
+
                fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
 #endif         /* 2.6 */
 
-               printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
+               printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);
 
 #ifdef CONFIG_MTRR
                ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
                                        MTRR_TYPE_WRCOMB, 1);
-               if(!ivideo->mtrr) {
+               if(ivideo->mtrr < 0) {
                        printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
                }
 #endif
@@ -5591,14 +6614,9 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 
                if(register_framebuffer(sis_fb_info) < 0) {
                        printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
-                       iounmap(ivideo->video_vbase);
+                       ret = -EINVAL;
                        iounmap(ivideo->mmio_vbase);
-                       release_mem_region(ivideo->video_base, ivideo->video_size);
-                       release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
-                       if(ivideo->bios_abase) vfree(ivideo->bios_abase);
-                       pci_set_drvdata(pdev, NULL);
-                       kfree(sis_fb_info);
-                       return -EINVAL;
+                       goto error_0;
                }
 
                ivideo->registered = 1;
@@ -5607,21 +6625,47 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
                ivideo->next = card_list;
                card_list = ivideo;
 
+#ifdef SIS_OLD_CONFIG_COMPAT
+               {
+               int ret;
+               /* Our ioctls are all "32/64bit compatible" */
+               ret =  register_ioctl32_conversion(FBIO_ALLOC,             NULL);
+               ret |= register_ioctl32_conversion(FBIO_FREE,              NULL);
+               ret |= register_ioctl32_conversion(FBIOGET_VBLANK,         NULL);
+               ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE,    NULL);
+               ret |= register_ioctl32_conversion(SISFB_GET_INFO,         NULL);
+               ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET,  NULL);
+               ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET,  NULL);
+               ret |= register_ioctl32_conversion(SISFB_SET_LOCK,         NULL);
+               ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS,    NULL);
+               ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
+               ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
+               ret |= register_ioctl32_conversion(SISFB_COMMAND,          NULL);
+               if(ret)
+                       printk(KERN_ERR
+                               "sisfb: Error registering ioctl32 translations\n");
+               else
+                       ivideo->ioctl32registered = 1;
+               }
+#endif
+
                printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
-                    ivideo->sisfb_accel ? "enabled" : "disabled",
-                    ivideo->sisfb_ypan  ?
-                       (ivideo->sisfb_max ? "enabled (auto-max)" : "enabled (no auto-max)") : "disabled");
+                       ivideo->sisfb_accel ? "enabled" : "disabled",
+                       ivideo->sisfb_ypan  ?
+                               (ivideo->sisfb_max ? "enabled (auto-max)" :
+                                               "enabled (no auto-max)") :
+                                                                       "disabled");
 
 
-               printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%d\n",
+               printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-                       GET_FB_IDX(sis_fb_info->node),
+                       GET_FB_IDX(sis_fb_info->node),
 #else
-                       sis_fb_info->node,
+                       sis_fb_info->node,
 #endif
                        ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
 
-               printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
+               printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");
 
        }       /* if mode = "none" */
 
@@ -5634,26 +6678,62 @@ static int __devinit sisfb_probe(struct pci_dev *pdev,
 
 static void __devexit sisfb_remove(struct pci_dev *pdev)
 {
-       struct sis_video_info *ivideo = pci_get_drvdata(pdev);
-       struct fb_info        *sis_fb_info = ivideo->memyselfandi;
-       int                   registered = ivideo->registered;
+       struct sis_video_info   *ivideo = pci_get_drvdata(pdev);
+       struct fb_info          *sis_fb_info = ivideo->memyselfandi;
+       int                     registered = ivideo->registered;
+       int                     modechanged = ivideo->modechanged;
+
+#ifdef SIS_OLD_CONFIG_COMPAT
+       if(ivideo->ioctl32registered) {
+               int ret;
+               ret =  unregister_ioctl32_conversion(FBIO_ALLOC);
+               ret |= unregister_ioctl32_conversion(FBIO_FREE);
+               ret |= unregister_ioctl32_conversion(FBIOGET_VBLANK);
+               ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
+               ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
+               ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
+               ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
+               ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
+               ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
+               ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
+               ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
+               ret |= unregister_ioctl32_conversion(SISFB_COMMAND);
+               if(ret)
+                       printk(KERN_ERR
+                            "sisfb: Error unregistering ioctl32 translations\n");
+       }
+#endif
 
        /* Unmap */
-       iounmap(ivideo->video_vbase);
        iounmap(ivideo->mmio_vbase);
-       vfree(ivideo->bios_abase);
+       iounmap(ivideo->video_vbase);
 
        /* Release mem regions */
        release_mem_region(ivideo->video_base, ivideo->video_size);
        release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 
+       vfree(ivideo->bios_abase);
+
+       if(ivideo->lpcdev)
+               SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
+
+       if(ivideo->nbridge)
+               SIS_PCI_PUT_DEVICE(ivideo->nbridge);
+
 #ifdef CONFIG_MTRR
        /* Release MTRR region */
-       if(ivideo->mtrr) {
+       if(ivideo->mtrr >= 0)
                mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
-       }
 #endif
 
+       pci_set_drvdata(pdev, NULL);
+
+       /* If device was disabled when starting, disable
+        * it when quitting.
+        */
+       if(!ivideo->sisvga_enabled)
+               pci_disable_device(pdev);
+
        /* Unregister the framebuffer */
        if(ivideo->registered) {
                unregister_framebuffer(sis_fb_info);
@@ -5664,7 +6744,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
 #endif
        }
 
-       pci_set_drvdata(pdev, NULL);
+       /* OK, our ivideo is gone for good from here. */
 
        /* TODO: Restore the initial mode
         * This sounds easy but is as good as impossible
@@ -5673,15 +6753,15 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
         * from machine to machine. Depends on the type
         * of integration between chipset and bridge.
         */
-       if(registered) {
-          printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
-       }
+       if(registered && modechanged)
+               printk(KERN_INFO
+                       "sisfb: Restoring of text mode not supported yet\n");
 };
 
 static struct pci_driver sisfb_driver = {
        .name           = "sisfb",
        .id_table       = sisfb_pci_table,
-       .probe          = sisfb_probe,
+       .probe          = sisfb_probe,
        .remove         = __devexit_p(sisfb_remove)
 };
 
@@ -5693,10 +6773,11 @@ SISINITSTATIC int __init sisfb_init(void)
 
        if(fb_get_options("sisfb", &options))
                return -ENODEV;
+
        sisfb_setup(options);
 #endif
 #endif
-       return(pci_register_driver(&sisfb_driver));
+       return pci_register_driver(&sisfb_driver);
 }
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
@@ -5711,36 +6792,129 @@ module_init(sisfb_init);
 
 #ifdef MODULE
 
-static char         *mode = NULL;
-static int          vesa = -1;
-static unsigned int rate = 0;
-static unsigned int crt1off = 1;
-static unsigned int mem = 0;
-static char         *forcecrt2type = NULL;
-static int          forcecrt1 = -1;
-static int          pdc = -1;
-static int          pdc1 = -1;
-static int          noaccel = -1;
-static int          noypan  = -1;
-static int         nomax = -1;
+static char            *mode = NULL;
+static int             vesa = -1;
+static unsigned int    rate = 0;
+static unsigned int    crt1off = 1;
+static unsigned int    mem = 0;
+static char            *forcecrt2type = NULL;
+static int             forcecrt1 = -1;
+static int             pdc = -1;
+static int             pdc1 = -1;
+static int             noaccel = -1;
+static int             noypan  = -1;
+static int             nomax = -1;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int             inverse = 0;
+#endif
+static int             userom = -1;
+static int             useoem = -1;
+static char            *tvstandard = NULL;
+static int             nocrt2rate = 0;
+static int             scalelcd = -1;
+static char            *specialtiming = NULL;
+static int             lvdshl = -1;
+static int             tvxposoffset = 0, tvyposoffset = 0;
+#if !defined(__i386__) && !defined(__x86_64__)
+static int             resetcard = 0;
+static int             videoram = 0;
+#endif
+
+static int __init sisfb_init_module(void)
+{
+       sisfb_setdefaultparms();
+
+       if(rate)
+               sisfb_parm_rate = rate;
+
+       if((scalelcd == 0) || (scalelcd == 1))
+               sisfb_scalelcd = scalelcd ^ 1;
+
+       /* Need to check crt2 type first for fstn/dstn */
+
+       if(forcecrt2type)
+               sisfb_search_crt2type(forcecrt2type);
+
+       if(tvstandard)
+               sisfb_search_tvstd(tvstandard);
+
+       if(mode)
+               sisfb_search_mode(mode, FALSE);
+       else if(vesa != -1)
+               sisfb_search_vesamode(vesa, FALSE);
+
+       sisfb_crt1off = (crt1off == 0) ? 1 : 0;
+
+       sisfb_forcecrt1 = forcecrt1;
+       if(forcecrt1 == 1)
+               sisfb_crt1off = 0;
+       else if(forcecrt1 == 0)
+               sisfb_crt1off = 1;
+
+       if(noaccel == 1)
+               sisfb_accel = 0;
+       else if(noaccel == 0)
+               sisfb_accel = 1;
+
+       if(noypan == 1)
+               sisfb_ypan = 0;
+       else if(noypan == 0)
+               sisfb_ypan = 1;
+
+       if(nomax == 1)
+               sisfb_max = 0;
+       else if(nomax == 0)
+               sisfb_max = 1;
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static int          inverse = 0;
-#endif
-static int          userom = -1;
-static int          useoem = -1;
-static char         *tvstandard = NULL;
-static int         nocrt2rate = 0;
-static int          scalelcd = -1;
-static char        *specialtiming = NULL;
-static int         lvdshl = -1;
-static int         tvxposoffset = 0, tvyposoffset = 0;
-static int         filter = -1;
+       if(inverse) sisfb_inverse = 1;
+#endif
+
+       if(mem)
+               sisfb_parm_mem = mem;
+
+       if(userom != -1)
+               sisfb_userom = userom;
+
+       if(useoem != -1)
+               sisfb_useoem = useoem;
+
+        if(pdc != -1)
+               sisfb_pdc  = (pdc  & 0x7f);
+
+       if(pdc1 != -1)
+               sisfb_pdca = (pdc1 & 0x1f);
+
+       sisfb_nocrt2rate = nocrt2rate;
+
+       if(specialtiming)
+               sisfb_search_specialtiming(specialtiming);
+
+       if((lvdshl >= 0) && (lvdshl <= 3))
+               sisfb_lvdshl = lvdshl;
+
+       sisfb_tvxposoffset = tvxposoffset;
+       sisfb_tvyposoffset = tvyposoffset;
+
 #if !defined(__i386__) && !defined(__x86_64__)
-static int         resetcard = 0;
-static int         videoram = 0;
+       sisfb_resetcard = (resetcard) ? 1 : 0;
+       if(videoram)
+               sisfb_videoram = videoram;
 #endif
 
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
+       return sisfb_init();
+}
+
+static void __exit sisfb_remove_module(void)
+{
+       pci_unregister_driver(&sisfb_driver);
+       printk(KERN_DEBUG "sisfb: Module unloaded\n");
+}
+
+module_init(sisfb_init_module);
+module_exit(sisfb_remove_module);
+
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/55x/65x/661/74x/330/76x/34x, XGI V3XT/V5/V8/Z7 framebuffer device driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
 
@@ -5764,7 +6938,6 @@ MODULE_PARM(lvdshl, "i");
 MODULE_PARM(tvstandard, "s");
 MODULE_PARM(tvxposoffset, "i");
 MODULE_PARM(tvyposoffset, "i");
-MODULE_PARM(filter, "i");
 MODULE_PARM(nocrt2rate, "i");
 MODULE_PARM(inverse, "i");
 #if !defined(__i386__) && !defined(__x86_64__)
@@ -5793,7 +6966,6 @@ module_param(lvdshl, int, 0);
 module_param(tvstandard, charp, 0);
 module_param(tvxposoffset, int, 0);
 module_param(tvyposoffset, int, 0);
-module_param(filter, int, 0);
 module_param(nocrt2rate, int, 0);
 #if !defined(__i386__) && !defined(__x86_64__)
 module_param(resetcard, int, 0);
@@ -5801,25 +6973,35 @@ module_param(videoram, int, 0);
 #endif
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 MODULE_PARM_DESC(mem,
        "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
          "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
          "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
          "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
-         "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+         "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
          "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
          "for XFree86 4.x/X.org 6.7 and later.\n");
+#else
+MODULE_PARM_DESC(mem,
+       "\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+         "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+         "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+         "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+         "otherwise at 12288KB. On 315/330/340 series, the heap size is 32KB by default.\n"
+         "The value is to be specified without 'KB'.\n");
+#endif
 
 MODULE_PARM_DESC(noaccel,
-        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+       "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
          "(default: 0)\n");
 
 MODULE_PARM_DESC(noypan,
-        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
-         "will be performed by redrawing the screen. (default: 0)\n");
+       "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+         "will be performed by redrawing the screen. (default: 0)\n");
 
 MODULE_PARM_DESC(nomax,
-        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+       "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
          "memory for the virtual screen in order to optimize scrolling performance. If\n"
          "this is set to anything other than 0, sisfb will not do this and thereby \n"
          "enable the user to positively specify a virtual Y size of the screen using\n"
@@ -5827,30 +7009,30 @@ MODULE_PARM_DESC(nomax,
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 MODULE_PARM_DESC(mode,
-        "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
-          "1024x768x16. Other formats supported include XxY-Depth and\n"
-         "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+       "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+         "1024x768x16. Other formats supported include XxY-Depth and\n"
+         "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
          "number, it will be interpreted as a VESA mode number. (default: none if\n"
          "sisfb is a module; this leaves the console untouched and the driver will\n"
          "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
          "is in the kernel)\n");
 MODULE_PARM_DESC(vesa,
-        "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
-          "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
+       "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
+         "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
          "and the driver will only do the video memory management for eg. DRM/DRI;\n"
          "0x0103 if sisfb is in the kernel)\n");
 #endif
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 MODULE_PARM_DESC(mode,
-       "\nSelects the desired default display mode in the format XxYxDepth,\n"
-         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+       "\nSelects the desired default display mode in the format XxYxDepth,\n"
+        "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
         "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
         "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
 
 MODULE_PARM_DESC(vesa,
-       "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
-         "0x117 (default: 0x0103)\n");
+       "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
+        "0x117 (default: 0x0103)\n");
 #endif
 
 MODULE_PARM_DESC(rate,
@@ -5880,16 +7062,16 @@ MODULE_PARM_DESC(scalelcd,
          "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");
 
 MODULE_PARM_DESC(pdc,
-        "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
+       "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
          "should detect this correctly in most cases; however, sometimes this is not\n"
          "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
-         "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
-         "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
-         "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
+         "on a 300 series chipset; 6 on other chipsets. If the problem persists, try\n"
+         "other values (on 300 series: between 4 and 60 in steps of 4; otherwise: any\n"
+         "value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
 
 #ifdef CONFIG_FB_SIS_315
 MODULE_PARM_DESC(pdc1,
-        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+       "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330/340\n"
          "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
          "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
          "implemented yet.\n");
@@ -5913,17 +7095,13 @@ MODULE_PARM_DESC(tvyposoffset,
        "\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
          "Default: 0\n");
 
-MODULE_PARM_DESC(filter,
-       "\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
-         "(Possible values 0-7, default: [no filter])\n");
-
 MODULE_PARM_DESC(nocrt2rate,
        "\nSetting this to 1 will force the driver to use the default refresh rate for\n"
          "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 MODULE_PARM_DESC(inverse,
-        "\nSetting this to anything but 0 should invert the display colors, but this\n"
+       "\nSetting this to anything but 0 should invert the display colors, but this\n"
          "does not seem to work. (default: 0)\n");
 #endif
 
@@ -5931,98 +7109,23 @@ MODULE_PARM_DESC(inverse,
 #ifdef CONFIG_FB_SIS_300
 MODULE_PARM_DESC(resetcard,
        "\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
-         "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
-         "Default: 0\n");
+         "the BIOS did not POST the card (only supported for SiS 300/305 and XGI cards\n"
+         "currently). Default: 0\n");
 
 MODULE_PARM_DESC(videoram,
        "\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
          "some non-x86 architectures where the memory auto detection fails. Only\n"
-         "relevant if resetcard is set, too. Default: [auto-detect]\n");
-#endif
-#endif
-
-static int __devinit sisfb_init_module(void)
-{
-       sisfb_setdefaultparms();
-
-       if(rate) sisfb_parm_rate = rate;
-
-       if((scalelcd == 0) || (scalelcd == 1)) {
-          sisfb_scalelcd = scalelcd ^ 1;
-       }
-
-       /* Need to check crt2 type first for fstn/dstn */
-
-       if(forcecrt2type)
-               sisfb_search_crt2type(forcecrt2type);
-
-       if(tvstandard)
-               sisfb_search_tvstd(tvstandard);
-
-       if(mode)
-               sisfb_search_mode(mode, FALSE);
-       else if(vesa != -1)
-               sisfb_search_vesamode(vesa, FALSE);
-
-       sisfb_crt1off = (crt1off == 0) ? 1 : 0;
-
-       sisfb_forcecrt1 = forcecrt1;
-       if(forcecrt1 == 1)      sisfb_crt1off = 0;
-       else if(forcecrt1 == 0) sisfb_crt1off = 1;
-
-       if(noaccel == 1)      sisfb_accel = 0;
-       else if(noaccel == 0) sisfb_accel = 1;
-
-       if(noypan == 1)       sisfb_ypan = 0;
-       else if(noypan == 0)  sisfb_ypan = 1;
-
-       if(nomax == 1)        sisfb_max = 0;
-       else if(nomax == 0)   sisfb_max = 1;
-       
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-       if(inverse)           sisfb_inverse = 1;
+         "relevant if resetcard is set, too. SiS300/305 only. Default: [auto-detect]\n");
 #endif
-
-       if(mem)               sisfb_parm_mem = mem;
-
-       if(userom != -1)      sisfb_userom = userom;
-       if(useoem != -1)      sisfb_useoem = useoem;
-
-        if(pdc != -1)  sisfb_pdc  = (pdc  & 0x7f);
-       if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
-
-       sisfb_nocrt2rate = nocrt2rate;
-
-       if(specialtiming)
-               sisfb_search_specialtiming(specialtiming);
-
-       if((lvdshl >= 0) && (lvdshl <= 3))  sisfb_lvdshl = lvdshl;
-
-       if(filter != -1) sisfb_filter = filter;
-
-       sisfb_tvxposoffset = tvxposoffset;
-       sisfb_tvyposoffset = tvyposoffset;
-
-#if !defined(__i386__) && !defined(__x86_64__)
-       sisfb_resetcard = (resetcard) ? 1 : 0;
-       if(videoram)    sisfb_videoram = videoram;
 #endif
 
-        return(sisfb_init());
-}
-
-static void __exit sisfb_remove_module(void)
-{
-       pci_unregister_driver(&sisfb_driver);
-       printk(KERN_DEBUG "sisfb: Module unloaded\n");
-}
-
-module_init(sisfb_init_module);
-module_exit(sisfb_remove_module);
-
 #endif            /*  /MODULE  */
 
+/* _GPL only for new symbols. */
 EXPORT_SYMBOL(sis_malloc);
 EXPORT_SYMBOL(sis_free);
+EXPORT_SYMBOL_GPL(sis_malloc_new);
+EXPORT_SYMBOL_GPL(sis_free_new);
+
 
 
index a6678a7aff35de2301efbeb81d75f3964242da59..445bcbba03aefd54e336c5c1f436bf4d858bfe75 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * SiS 300/305/540/630(S)/730(S)
- * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * SiS 300/305/540/630(S)/730(S),
+ * SiS 315[E|PRO]/550/[M]65x/[M]66x[F|M|G]X/[M]74x[GX]/330/[M]76x[GX],
+ * XGI V3XT/V5/V8, Z7
  * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
  *
- * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ * Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
  *
  * 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
 #ifndef _SISFB_MAIN
 #define _SISFB_MAIN
 
-#include <linux/spinlock.h>
-
 #include "vstruct.h"
 #include "sis.h"
 
-#define MODE_INDEX_NONE           0  /* index for mode=none */
-
 /* Fbcon stuff */
 static struct fb_var_screeninfo my_default_var = {
        .xres            = 0,
@@ -60,6 +57,8 @@ static struct fb_var_screeninfo my_default_var = {
        .vmode           = FB_VMODE_NONINTERLACED,
 };
 
+#define MODE_INDEX_NONE           0  /* index for mode=none */
+
 /* Boot-time parameters */
 static int sisfb_off = 0;
 static int sisfb_parm_mem = 0;
@@ -93,7 +92,6 @@ static int sisfb_tvplug = -1;         /* Tv plug type (for overriding autodetection) */
 static int sisfb_tvstd  = -1;
 static int sisfb_tvxposoffset = 0;
 static int sisfb_tvyposoffset = 0;
-static int sisfb_filter = -1;
 static int sisfb_nocrt2rate = 0;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int  sisfb_inverse = 0;
@@ -106,12 +104,12 @@ static int sisfb_videoram = 0;
 
 /* List of supported chips */
 static struct sisfb_chip_info {
-        int            chip;
-       int             vgaengine;
+       int             chip;
+       int             vgaengine;
        int             mni;
-       int             hwcursor_size;
+       int             hwcursor_size;
        int             CRT2_write_enable;
-       const char      *chip_name;
+       const char      *chip_name;
 } sisfb_chip_info[] __devinitdata = {
        { SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
        { SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
@@ -123,6 +121,8 @@ static struct sisfb_chip_info {
        { SIS_650,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
        { SIS_330,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
        { SIS_660,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+       { XGI_20,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI Z7" },
+       { XGI_40,     SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "XGI V3XT/V5/V8" },
 };
 
 static struct pci_device_id __devinitdata sisfb_pci_table[] = {
@@ -139,6 +139,8 @@ static struct pci_device_id __devinitdata sisfb_pci_table[] = {
        { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_650_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
        { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_330,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
        { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_660_VGA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+       { PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_20,     PCI_ANY_ID, PCI_ANY_ID, 0, 0,10},
+       { PCI_VENDOR_ID_XGI,PCI_DEVICE_ID_XGI_40,     PCI_ANY_ID, PCI_ANY_ID, 0, 0,11},
 #endif
        { 0 }
 };
@@ -147,13 +149,12 @@ MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
 
 static struct sis_video_info *card_list = NULL;
 
-/* TODO: This is not handled card-wise because the DRM
-   does not refer to a unique fb when calling sis_alloc
-   or sis_free. Therefore, this is handled globally for
-   now (hoping that nobody is crazy enough to run two
-   SiS cards at the same time).
+/* The memory heap is now handled card-wise, by using
+   sis_malloc_new/sis_free_new. However, the DRM does
+   not do this yet. Until it does, we keep a "global"
+   heap which is actually the first card's one.
  */
-static SIS_HEAP        sisfb_heap;
+static struct SIS_HEAP *sisfb_heap;
 
 #define MD_SIS300 1
 #define MD_SIS315 2
@@ -181,8 +182,10 @@ static const struct _sisbios_mode {
        {"320x240x16",   {0x56,0x56}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
        {"320x240x24",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
        {"320x240x32",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-       {"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  480,  8, 1,  40, 30,           MD_SIS315},  /* FSTN */
-/*10*/ {"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  480, 16, 1,  40, 30,           MD_SIS315},  /* FSTN */
+#define MODE_FSTN_8    9
+#define MODE_FSTN_16   10
+       {"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15,           MD_SIS315},  /* FSTN */
+/*10*/ {"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15,           MD_SIS315},  /* FSTN */
        {"400x300x8",    {0x51,0x51}, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
        {"400x300x16",   {0x57,0x57}, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
        {"400x300x24",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
@@ -215,18 +218,20 @@ static const struct _sisbios_mode {
 /*40*/ {"800x480x16",   {0x7a,0x7a}, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
        {"800x480x24",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
        {"800x480x32",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-#define DEFAULT_MODE              43 /* index for 800x600x8 */
-#define DEFAULT_LCDMODE           43 /* index for 800x600x8 */
-#define DEFAULT_TVMODE            43 /* index for 800x600x8 */
+#define DEFAULT_MODE           43 /* index for 800x600x8 */
+#define DEFAULT_LCDMODE                43 /* index for 800x600x8 */
+#define DEFAULT_TVMODE         43 /* index for 800x600x8 */
        {"800x600x8",    {0x30,0x30}, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
        {"800x600x16",   {0x47,0x47}, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
        {"800x600x24",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
        {"800x600x32",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
        {"848x480x8",    {0x39,0x39}, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_848       48
        {"848x480x16",   {0x3b,0x3b}, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
        {"848x480x24",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
 /*50*/ {"848x480x32",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
        {"856x480x8",    {0x3f,0x3f}, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
+#define DEFAULT_MODE_856       52
        {"856x480x16",   {0x42,0x42}, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
        {"856x480x24",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
        {"856x480x32",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
@@ -270,42 +275,47 @@ static const struct _sisbios_mode {
        {"1280x800x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
        {"1280x800x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
        {"1280x800x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+       {"1280x854x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  854,  8, 1, 160, 53,           MD_SIS315},
+       {"1280x854x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  854, 16, 1, 160, 53,           MD_SIS315},
+       {"1280x854x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  854, 32, 1, 160, 53,           MD_SIS315},
+       {"1280x854x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  854, 32, 1, 160, 53,           MD_SIS315},
        {"1280x960x8",   {0x7c,0x7c}, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
-       {"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+/*100*/        {"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
        {"1280x960x24",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
        {"1280x960x32",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
        {"1280x1024x8",  {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
-/*100*/        {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+       {"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
        {"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
        {"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
        {"1360x768x8",   {0x48,0x48}, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
        {"1360x768x16",  {0x4b,0x4b}, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
        {"1360x768x24",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-       {"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+/*110*/        {"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
        {"1360x1024x8",  {0x67,0x67}, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
+#define DEFAULT_MODE_1360      112
        {"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
        {"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-/*110*/        {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+       {"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
        {"1400x1050x8",  {0x26,0x26}, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
        {"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
        {"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
        {"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
        {"1600x1200x8",  {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
-       {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+/*120*/        {"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
        {"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
        {"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
        {"1680x1050x8",  {0x17,0x17}, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
-/*120*/        {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
+       {"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
        {"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
        {"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
        {"1920x1080x8",  {0x2c,0x2c}, 0x0000, 0x0000, 1920, 1080,  8, 1, 240, 67,           MD_SIS315},
        {"1920x1080x16", {0x2d,0x2d}, 0x0000, 0x0000, 1920, 1080, 16, 1, 240, 67,           MD_SIS315},
        {"1920x1080x24", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
-       {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
+/*130*/        {"1920x1080x32", {0x73,0x73}, 0x0000, 0x0000, 1920, 1080, 32, 1, 240, 67,           MD_SIS315},
        {"1920x1440x8",  {0x68,0x68}, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
        {"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
        {"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-/*130*/        {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+       {"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
        {"2048x1536x8",  {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
        {"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
        {"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
@@ -313,13 +323,13 @@ static const struct _sisbios_mode {
        {"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
 };
 
-#define SIS_LCD_NUMBER 17
-static const struct _sis_lcd_data {
+#define SIS_LCD_NUMBER 18
+static struct _sis_lcd_data {
        u32 lcdtype;
        u16 xres;
        u16 yres;
        u8  default_mode_idx;
-} sis_lcd_data[] = {
+} sis_lcd_data[] __devinitdata = {
        { LCD_640x480,    640,  480,  23 },
        { LCD_800x600,    800,  600,  43 },
        { LCD_1024x600,  1024,  600,  67 },
@@ -329,34 +339,38 @@ static const struct _sis_lcd_data {
        { LCD_1280x720,  1280,  720,  83 },
        { LCD_1280x768,  1280,  768,  87 },
        { LCD_1280x800,  1280,  800,  91 },
-       { LCD_1280x960,  1280,  960,  95 },
-       { LCD_1280x1024, 1280, 1024,  99 },
-       { LCD_1400x1050, 1400, 1050, 111 },
-       { LCD_1680x1050, 1680, 1050, 119 },
-       { LCD_1600x1200, 1600, 1200, 115 },
-       { LCD_640x480_2,  640,  480,  23 },
-       { LCD_640x480_3,  640,  480,  23 },
-       { LCD_320x480,    320,  480,   9 },
+       { LCD_1280x854,  1280,  854,  95 },
+       { LCD_1280x960,  1280,  960,  99 },
+       { LCD_1280x1024, 1280, 1024, 103 },
+       { LCD_1400x1050, 1400, 1050, 115 },
+       { LCD_1680x1050, 1680, 1050, 123 },
+       { LCD_1600x1200, 1600, 1200, 119 },
+       { LCD_320x240_2,  320,  240,   9 },
+       { LCD_320x240_3,  320,  240,   9 },
+       { LCD_320x240,    320,  240,   9 },
 };
 
 /* CR36 evaluation */
-static const USHORT sis300paneltype[] =
-    { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
-      LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
-      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
-      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN };
-
-static const USHORT sis310paneltype[] =
-    { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
-      LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
-      LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-      LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN,   LCD_UNKNOWN };
-
-static const USHORT sis661paneltype[] =
-    { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
-      LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
-      LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-      LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN };
+static unsigned short sis300paneltype[] __devinitdata = {
+       LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+       LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
+       LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
+       LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN
+};
+
+static unsigned short sis310paneltype[] __devinitdata = {
+       LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+       LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
+       LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
+       LCD_320x240_2, LCD_320x240_3, LCD_UNKNOWN,   LCD_UNKNOWN
+};
+
+static unsigned short sis661paneltype[] __devinitdata = {
+       LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
+       LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
+       LCD_1280x854,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
+       LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN
+};
 
 #define FL_550_DSTN 0x01
 #define FL_550_FSTN 0x02
@@ -413,7 +427,6 @@ static const struct _sis_vrate {
 } sisfb_vrate[] = {
        {1,  320,  200,  70,  TRUE},
        {1,  320,  240,  60,  TRUE},
-       {1,  320,  480,  60,  TRUE},
        {1,  400,  300,  60,  TRUE},
        {1,  512,  384,  60,  TRUE},
        {1,  640,  400,  72,  TRUE},
@@ -437,10 +450,11 @@ static const struct _sis_vrate {
        {4, 1024,  768,  75, FALSE}, {5, 1024,  768,  85,  TRUE}, {6, 1024,  768, 100,  TRUE},
        {7, 1024,  768, 120,  TRUE},
        {1, 1152,  768,  60,  TRUE},
-       {1, 1152,  864,  60,  TRUE}, {1, 1152,  864,  75,  TRUE}, {2, 1152,  864,  84,  TRUE},
+       {1, 1152,  864,  60,  TRUE}, {2, 1152,  864,  75,  TRUE}, {3, 1152,  864,  84,  TRUE},
        {1, 1280,  720,  60,  TRUE}, {2, 1280,  720,  75,  TRUE}, {3, 1280,  720,  85,  TRUE},
        {1, 1280,  768,  60,  TRUE},
        {1, 1280,  800,  60,  TRUE},
+       {1, 1280,  854,  60,  TRUE},
        {1, 1280,  960,  60,  TRUE}, {2, 1280,  960,  85,  TRUE},
        {1, 1280, 1024,  43,  TRUE}, {2, 1280, 1024,  60,  TRUE}, {3, 1280, 1024,  75,  TRUE},
        {4, 1280, 1024,  85,  TRUE},
@@ -459,12 +473,12 @@ static const struct _sis_vrate {
        {0,    0,    0,   0, FALSE}
 };
 
-static const struct _sisfbddcsmodes {
+static struct _sisfbddcsmodes {
        u32 mask;
        u16 h;
        u16 v;
        u32 d;
-} sisfb_ddcsmodes[] = {
+} sisfb_ddcsmodes[] __devinitdata = {
        { 0x10000, 67, 75, 108000},
        { 0x08000, 48, 72,  50000},
        { 0x04000, 46, 75,  49500},
@@ -480,49 +494,49 @@ static const struct _sisfbddcsmodes {
        { 0x00001, 38, 60,  40000}
 };
 
-static const struct _sisfbddcfmodes {
+static struct _sisfbddcfmodes {
        u16 x;
        u16 y;
        u16 v;
        u16 h;
        u32 d;
-} sisfb_ddcfmodes[] = {
-       { 1280, 1024, 85, 92, 157500},
-       { 1600, 1200, 60, 75, 162000},
-       { 1600, 1200, 65, 82, 175500},
-       { 1600, 1200, 70, 88, 189000},
-       { 1600, 1200, 75, 94, 202500},
-       { 1600, 1200, 85, 107,229500},
-       { 1920, 1440, 60, 90, 234000},
-       { 1920, 1440, 75, 113,297000}
+} sisfb_ddcfmodes[] __devinitdata = {
+       { 1280, 1024, 85, 92, 157500},
+       { 1600, 1200, 60, 75, 162000},
+       { 1600, 1200, 65, 82, 175500},
+       { 1600, 1200, 70, 88, 189000},
+       { 1600, 1200, 75, 94, 202500},
+       { 1600, 1200, 85, 107,229500},
+       { 1920, 1440, 60, 90, 234000},
+       { 1920, 1440, 75, 113,297000}
 };
 
 #ifdef CONFIG_FB_SIS_300
 static struct _chswtable {
-    u16  subsysVendor;
-    u16  subsysCard;
-    char *vendorName;
-    char *cardName;
+       u16  subsysVendor;
+       u16  subsysCard;
+       char *vendorName;
+       char *cardName;
 } mychswtable[] __devinitdata = {
-        { 0x1631, 0x1002, "Mitachi", "0x1002" },
+       { 0x1631, 0x1002, "Mitachi", "0x1002" },
        { 0x1071, 0x7521, "Mitac"  , "7521P"  },
        { 0,      0,      ""       , ""       }
 };
 #endif
 
 static struct _customttable {
-    u16   chipID;
-    char  *biosversion;
-    char  *biosdate;
-    u32   bioschksum;
-    u16   biosFootprintAddr[5];
-    u8    biosFootprintData[5];
-    u16   pcisubsysvendor;
-    u16   pcisubsyscard;
-    char  *vendorName;
-    char  *cardName;
-    u32   SpecialID;
-    char  *optionName;
+       u16   chipID;
+       char  *biosversion;
+       char  *biosdate;
+       u32   bioschksum;
+       u16   biosFootprintAddr[5];
+       u8    biosFootprintData[5];
+       u16   pcisubsysvendor;
+       u16   pcisubsyscard;
+       char  *vendorName;
+       char  *cardName;
+       u32   SpecialID;
+       char  *optionName;
 } mycustomttable[] __devinitdata = {
        { SIS_630, "2.00.07", "09/27/2002-13:38:25",
          0x3240A8,
@@ -643,6 +657,13 @@ static struct _customttable {
          0, 0,
          "Generic", "LVDS/Parallel 848x480", CUT_PANEL848, "PANEL848x480"
        },
+       { 4322, "", "",                 /* never autodetected */
+         0,
+         { 0, 0, 0, 0, 0 },
+         { 0, 0, 0, 0, 0 },
+         0, 0,
+         "Generic", "LVDS/Parallel 856x480", CUT_PANEL856, "PANEL856x480"
+       },
        { 0, "", "",
          0,
          { 0, 0, 0, 0 },
@@ -652,155 +673,6 @@ static struct _customttable {
        }
 };
 
-static const struct _sis_TV_filter {
-       u8 filter[9][4];
-} sis_TV_filter[] = {
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_0 */
-          {0x00,0xE0,0x10,0x60},
-          {0x00,0xEE,0x10,0x44},
-          {0x00,0xF4,0x10,0x38},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0x00,0x00,0x10,0x20},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_1 */
-          {0x00,0xE0,0x10,0x60},
-          {0x00,0xEE,0x10,0x44},
-          {0x00,0xF4,0x10,0x38},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0x00,0x00,0x10,0x20},
-          {0x00,0x04,0x10,0x18},
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_2 */
-          {0xF5,0xEE,0x1B,0x44},
-          {0xF8,0xF4,0x18,0x38},
-          {0xEB,0x04,0x25,0x18},
-          {0xF1,0x05,0x1F,0x16},
-          {0xF6,0x06,0x1A,0x14},
-          {0xFA,0x06,0x16,0x14},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_3 */
-          {0xF1,0x04,0x1F,0x18},
-          {0xEE,0x0D,0x22,0x06},
-          {0xF7,0x06,0x19,0x14},
-          {0xF4,0x0B,0x1C,0x0A},
-          {0xFA,0x07,0x16,0x12},
-          {0xF9,0x0A,0x17,0x0C},
-          {0x00,0x07,0x10,0x12}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_4 - 320 */
-          {0x00,0xE0,0x10,0x60},
-          {0x00,0xEE,0x10,0x44},
-          {0x00,0xF4,0x10,0x38},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0x00,0x00,0x10,0x20},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_5 - 640 */
-          {0xF5,0xEE,0x1B,0x44},
-          {0xF8,0xF4,0x18,0x38},
-          {0xEB,0x04,0x25,0x18},
-          {0xF1,0x05,0x1F,0x16},
-          {0xF6,0x06,0x1A,0x14},
-          {0xFA,0x06,0x16,0x14},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_6 - 720 */
-          {0xEB,0x04,0x25,0x18},
-          {0xE7,0x0E,0x29,0x04},
-          {0xEE,0x0C,0x22,0x08},
-          {0xF6,0x0B,0x1A,0x0A},
-          {0xF9,0x0A,0x17,0x0C},
-          {0xFC,0x0A,0x14,0x0C},
-          {0x00,0x08,0x10,0x10}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* NTSCFilter_7 - 800 */
-          {0xEC,0x02,0x24,0x1C},
-          {0xF2,0x04,0x1E,0x18},
-          {0xEB,0x15,0x25,0xF6},
-          {0xF4,0x10,0x1C,0x00},
-          {0xF8,0x0F,0x18,0x02},
-          {0x00,0x04,0x10,0x18},
-          {0x01,0x06,0x0F,0x14}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_0 */
-          {0x00,0xE0,0x10,0x60},
-          {0x00,0xEE,0x10,0x44},
-          {0x00,0xF4,0x10,0x38},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0x00,0x00,0x10,0x20},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_1 */
-          {0x00,0xE0,0x10,0x60},
-          {0x00,0xEE,0x10,0x44},
-          {0x00,0xF4,0x10,0x38},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0x00,0x00,0x10,0x20},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_2 */
-          {0xF5,0xEE,0x1B,0x44},
-          {0xF8,0xF4,0x18,0x38},
-          {0xF1,0xF7,0x01,0x32},
-          {0xF5,0xFB,0x1B,0x2A},
-          {0xF9,0xFF,0x17,0x22},
-          {0xFB,0x01,0x15,0x1E},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_3 */
-          {0xF5,0xFB,0x1B,0x2A},
-          {0xEE,0xFE,0x22,0x24},
-          {0xF3,0x00,0x1D,0x20},
-          {0xF9,0x03,0x17,0x1A},
-          {0xFB,0x02,0x14,0x1E},
-          {0xFB,0x04,0x15,0x18},
-          {0x00,0x06,0x10,0x14}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_4 - 320 */
-          {0x00,0xE0,0x10,0x60},
-          {0x00,0xEE,0x10,0x44},
-          {0x00,0xF4,0x10,0x38},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0x00,0x00,0x10,0x20},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_5 - 640 */
-          {0xF5,0xEE,0x1B,0x44},
-          {0xF8,0xF4,0x18,0x38},
-          {0xF1,0xF7,0x1F,0x32},
-          {0xF5,0xFB,0x1B,0x2A},
-          {0xF9,0xFF,0x17,0x22},
-          {0xFB,0x01,0x15,0x1E},
-          {0x00,0x04,0x10,0x18}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_6 - 720 */
-          {0xF5,0xEE,0x1B,0x2A},
-          {0xEE,0xFE,0x22,0x24},
-          {0xF3,0x00,0x1D,0x20},
-          {0xF9,0x03,0x17,0x1A},
-          {0xFB,0x02,0x14,0x1E},
-          {0xFB,0x04,0x15,0x18},
-          {0x00,0x06,0x10,0x14}, 
-          {0xFF,0xFF,0xFF,0xFF} }},
-       { {{0x00,0x00,0x00,0x40},  /* PALFilter_7 - 800 */
-          {0xF5,0xEE,0x1B,0x44},
-          {0xF8,0xF4,0x18,0x38},
-          {0xFC,0xFB,0x14,0x2A},
-          {0xEB,0x05,0x25,0x16},
-          {0xF1,0x05,0x1F,0x16},
-          {0xFA,0x07,0x16,0x12},
-          {0x00,0x07,0x10,0x12}, 
-          {0xFF,0xFF,0xFF,0xFF} }}
-};
-
 /* ---------------------- Prototypes ------------------------- */
 
 /* Interface used by the world */
@@ -811,145 +683,159 @@ SISINITSTATIC int sisfb_setup(char *options);
 /* Interface to the low level console driver */
 SISINITSTATIC int sisfb_init(void);
 
-
 /* fbdev routines */
-static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-                             struct fb_info *info);
+static int     sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                               struct fb_info *info);
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, 
-                             int con,
-                             struct fb_info *info);
-static int      sisfb_get_var(struct fb_var_screeninfo *var, 
-                             int con,
-                             struct fb_info *info);
-static int      sisfb_set_var(struct fb_var_screeninfo *var, 
-                             int con,
-                             struct fb_info *info);
-static void     sisfb_crtc_to_var(struct sis_video_info *ivideo,
-                                 struct fb_var_screeninfo *var);
-static int      sisfb_get_cmap(struct fb_cmap *cmap, 
-                              int kspc, 
-                              int con,
-                              struct fb_info *info);
-static int      sisfb_set_cmap(struct fb_cmap *cmap, 
-                              int kspc, 
-                              int con,
-                              struct fb_info *info);                   
-static int      sisfb_update_var(int con, 
-                                struct fb_info *info);
-static int      sisfb_switch(int con, 
+static int     sisfb_get_fix(struct fb_fix_screeninfo *fix,
+                               int con,
+                               struct fb_info *info);
+static int     sisfb_get_var(struct fb_var_screeninfo *var,
+                               int con,
+                               struct fb_info *info);
+static int     sisfb_set_var(struct fb_var_screeninfo *var,
+                               int con,
+                               struct fb_info *info);
+static void    sisfb_crtc_to_var(struct sis_video_info *ivideo,
+                               struct fb_var_screeninfo *var);
+static int     sisfb_get_cmap(struct fb_cmap *cmap,
+                               int kspc,
+                               int con,
+                               struct fb_info *info);
+static int     sisfb_set_cmap(struct fb_cmap *cmap,
+                               int kspc,
+                               int con,
+                               struct fb_info *info);
+static int     sisfb_update_var(int con,
+                               struct fb_info *info);
+static int     sisfb_switch(int con,
                             struct fb_info *info);
-static void     sisfb_blank(int blank, 
-                           struct fb_info *info);
-static void     sisfb_set_disp(int con, 
-                              struct fb_var_screeninfo *var, 
-                               struct fb_info *info);
-static int      sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-                             unsigned *blue, unsigned *transp,
-                             struct fb_info *fb_info);
-static void     sisfb_do_install_cmap(int con, 
-                                      struct fb_info *info);
-static int      sisfb_ioctl(struct inode *inode, struct file *file,
-                           unsigned int cmd, unsigned long arg, int con,
-                           struct fb_info *info);                    
-#endif                 
+static void    sisfb_blank(int blank,
+                               struct fb_info *info);
+static void    sisfb_set_disp(int con,
+                               struct fb_var_screeninfo *var,
+                               struct fb_info *info);
+static int     sis_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+                               unsigned *blue, unsigned *transp,
+                               struct fb_info *fb_info);
+static void    sisfb_do_install_cmap(int con,
+                               struct fb_info *info);
+static int     sisfb_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, unsigned long arg, int con,
+                               struct fb_info *info);
+#endif
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int      sisfb_ioctl(struct inode *inode, struct file *file,
-                           unsigned int cmd, unsigned long arg,
-                           struct fb_info *info);
-static int      sisfb_set_par(struct fb_info *info);
-static int      sisfb_blank(int blank, 
-                            struct fb_info *info);                     
-extern void     fbcon_sis_fillrect(struct fb_info *info, 
-                                   const struct fb_fillrect *rect);
-extern void     fbcon_sis_copyarea(struct fb_info *info, 
-                                   const struct fb_copyarea *area);
-extern int      fbcon_sis_sync(struct fb_info *info);
+static int     sisfb_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, unsigned long arg,
+                               struct fb_info *info);
+static int     sisfb_set_par(struct fb_info *info);
+static int     sisfb_blank(int blank,
+                               struct fb_info *info);
+extern void    fbcon_sis_fillrect(struct fb_info *info,
+                               const struct fb_fillrect *rect);
+extern void    fbcon_sis_copyarea(struct fb_info *info,
+                               const struct fb_copyarea *area);
+extern int     fbcon_sis_sync(struct fb_info *info);
 #endif
-                       
+
 /* Internal 2D accelerator functions */
-extern int      sisfb_initaccel(struct sis_video_info *ivideo);
-extern void     sisfb_syncaccel(struct sis_video_info *ivideo);
+extern int     sisfb_initaccel(struct sis_video_info *ivideo);
+extern void    sisfb_syncaccel(struct sis_video_info *ivideo);
 
 /* Internal general routines */
-static void     sisfb_search_mode(char *name, BOOLEAN quiet);
-static int      sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
-static u8       sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
-                       int index);
-static int      sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-                       unsigned blue, unsigned transp,
-                       struct fb_info *fb_info);
-static int      sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
-                       struct fb_info *info);
-static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
-static void     sisfb_post_setmode(struct sis_video_info *ivideo);
-static BOOLEAN  sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
-static BOOLEAN  sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
-static BOOLEAN  sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
-static BOOLEAN  sisfb_bridgeisslave(struct sis_video_info *ivideo);
-static void     sisfb_detect_VB_connect(struct sis_video_info *ivideo);
-static void     sisfb_get_VB_type(struct sis_video_info *ivideo);
-static void     sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
-static void     sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+static void    sisfb_search_mode(char *name, BOOLEAN quiet);
+static int     sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8      sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate,
+                               int index);
+static int     sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                               unsigned blue, unsigned transp,
+                               struct fb_info *fb_info);
+static int     sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
+                               struct fb_info *info);
+static void    sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void    sisfb_post_setmode(struct sis_video_info *ivideo);
+static BOOLEAN sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static BOOLEAN sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static BOOLEAN sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static BOOLEAN sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void    sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void    sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void    sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void    sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
+#ifdef CONFIG_FB_SIS_300
+unsigned int   sisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+void           sisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val);
+unsigned int   sisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg);
+#endif
+#ifdef CONFIG_FB_SIS_315
+void           sisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val);
+unsigned int   sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg);
+#endif
 
 /* SiS-specific exported functions */
-void            sis_malloc(struct sis_memreq *req);
-void            sis_free(u32 base);
+void                   sis_malloc(struct sis_memreq *req);
+void                   sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+void                   sis_free(u32 base);
+void                   sis_free_new(struct pci_dev *pdev, u32 base);
 
 /* Internal heap routines */
-static int      sisfb_heap_init(struct sis_video_info *ivideo);
-static SIS_OH   *sisfb_poh_new_node(void);
-static SIS_OH   *sisfb_poh_allocate(u32 size);
-static void     sisfb_delete_node(SIS_OH *poh);
-static void     sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh);
-static SIS_OH   *sisfb_poh_free(u32 base);
-static void     sisfb_free_node(SIS_OH *poh);
-
-/* Sensing routines */
-static void     SiS_Sense30x(struct sis_video_info *ivideo);
-static void     SiS_SenseCh(struct sis_video_info *ivideo);
+static int             sisfb_heap_init(struct sis_video_info *ivideo);
+static struct SIS_OH * sisfb_poh_new_node(struct SIS_HEAP *memheap);
+static struct SIS_OH * sisfb_poh_allocate(struct SIS_HEAP *memheap, u32 size);
+static void            sisfb_delete_node(struct SIS_OH *poh);
+static void            sisfb_insert_node(struct SIS_OH *pohList, struct SIS_OH *poh);
+static struct SIS_OH * sisfb_poh_free(struct SIS_HEAP *memheap, u32 base);
+static void            sisfb_free_node(struct SIS_HEAP *memheap, struct SIS_OH *poh);
 
 /* Routines from init.c/init301.c */
-extern USHORT   SiS_GetModeID_LCD(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth,
-                                  BOOLEAN FSTN, USHORT CustomT, int LCDwith, int LCDheight);
-extern USHORT   SiS_GetModeID_TV(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-extern USHORT   SiS_GetModeID_VGA2(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth);
-
-extern void    SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
-extern BOOLEAN  SiSSetMode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo, USHORT ModeNo);
-extern void     SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable);
-extern void     SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable);
-
-extern BOOLEAN  SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo);
-
-extern BOOLEAN  sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
-                      unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+extern unsigned short  SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay,
+                               int VDisplay, int Depth, BOOLEAN FSTN, unsigned short CustomT,
+                               int LCDwith, int LCDheight, unsigned int VBFlags2);
+extern unsigned short  SiS_GetModeID_TV(int VGAEngine, unsigned int VBFlags, int HDisplay,
+                               int VDisplay, int Depth, unsigned int VBFlags2);
+extern unsigned short  SiS_GetModeID_VGA2(int VGAEngine, unsigned int VBFlags, int HDisplay,
+                               int VDisplay, int Depth, unsigned int VBFlags2);
+extern void            SiSRegInit(struct SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr);
+extern BOOLEAN         SiSSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
+extern void            SiS_SetEnableDstn(struct SiS_Private *SiS_Pr, int enable);
+extern void            SiS_SetEnableFstn(struct SiS_Private *SiS_Pr, int enable);
+
+extern BOOLEAN         SiSDetermineROMLayout661(struct SiS_Private *SiS_Pr);
+
+extern BOOLEAN         sisfb_gettotalfrommode(struct SiS_Private *SiS_Pr, unsigned char modeno,
+                               int *htotal, int *vtotal, unsigned char rateindex);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-extern int     sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr,
-                       PSIS_HW_INFO HwDeviceExtension,
-                       unsigned char modeno, unsigned char rateindex);
-extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
-                       unsigned char modeno, unsigned char rateindex,
-                       struct fb_var_screeninfo *var);
+extern int             sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr,
+                               unsigned char modeno, unsigned char rateindex);
+extern int             sisfb_mode_rate_to_ddata(struct SiS_Private *SiS_Pr, unsigned char modeno,
+                               unsigned char rateindex, struct fb_var_screeninfo *var);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+extern void            SiS_Generic_ConvertCRData(struct SiS_Private *SiS_Pr, unsigned char *crdata, int xres,
+                               int yres, struct fb_var_screeninfo *var, BOOLEAN writeres);
 #endif
 
 /* Chrontel TV, DDC and DPMS functions */
-extern USHORT  SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void    SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern USHORT  SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void    SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
-extern void     SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
-extern void     SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-extern void     SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-extern USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
-                             USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
-extern USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-extern void    SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-extern void    SiS_Chrontel701xBLOff(SiS_Private *SiS_Pr);
-extern void    SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
-extern void    SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
+extern unsigned short  SiS_GetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void            SiS_SetCH700x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern unsigned short  SiS_GetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg);
+extern void            SiS_SetCH701x(struct SiS_Private *SiS_Pr, unsigned short reg, unsigned char val);
+extern void            SiS_SetCH70xxANDOR(struct SiS_Private *SiS_Pr, unsigned short reg,
+                               unsigned char myor, unsigned char myand);
+extern void            SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime);
+extern void            SiS_SetChrontelGPIO(struct SiS_Private *SiS_Pr, unsigned short myvbinfo);
+extern unsigned short  SiS_HandleDDC(struct SiS_Private *SiS_Pr, unsigned int VBFlags, int VGAEngine,
+                               unsigned short adaptnum, unsigned short DDCdatatype, unsigned char *buffer,
+                               unsigned int VBFlags2);
+extern unsigned short  SiS_ReadDDC1Bit(struct SiS_Private *SiS_Pr);
+#ifdef CONFIG_FB_SIS_315
+extern void            SiS_Chrontel701xBLOn(struct SiS_Private *SiS_Pr);
+extern void            SiS_Chrontel701xBLOff(struct SiS_Private *SiS_Pr);
+#endif
+extern void            SiS_SiS30xBLOn(struct SiS_Private *SiS_Pr);
+extern void            SiS_SiS30xBLOff(struct SiS_Private *SiS_Pr);
 #endif
 
 
index 507bba1a71b5df8821887c6eb1b48f6588426b60..831b9f42264bb8590d1cebf3c978ac8b4114a5f0 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * General type definitions for universal mode switching modules
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-#ifndef _VGATYPES_
-#define _VGATYPES_
+#ifndef _VGATYPES_H_
+#define _VGATYPES_H_
 
-#ifdef LINUX_KERNEL  /* We don't want the X driver to depend on kernel source */
-#include <linux/ioctl.h>
+#ifdef SIS_LINUX_KERNEL
 #include <linux/version.h>
 #endif
 
 #define TRUE    1
 #endif
 
-#ifndef NULL
-#define NULL    0
-#endif
-
-#ifndef CHAR
-typedef char CHAR;
-#endif
-
-#ifndef SHORT
-typedef short SHORT;
-#endif
-
-#ifndef LONG
-typedef long  LONG;
-#endif
-
-#ifndef UCHAR
-typedef unsigned char UCHAR;
-#endif
-
-#ifndef USHORT
-typedef unsigned short USHORT;
-#endif
-
-#ifndef ULONG
-typedef unsigned long ULONG;
-#endif
-
 #ifndef BOOLEAN
-typedef unsigned char BOOLEAN;
+typedef unsigned int BOOLEAN;
 #endif
 
 #define SISIOMEMTYPE
 
-#ifdef LINUX_KERNEL
+#ifdef SIS_LINUX_KERNEL
 typedef unsigned long SISIOADDRESS;
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
 #include <linux/types.h>  /* Need __iomem */
@@ -109,7 +80,7 @@ typedef unsigned long SISIOADDRESS;
 #endif
 #endif
 
-#ifdef LINUX_XF86
+#ifdef SIS_XORG_XF86
 #if XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,2,0,0,0)
 typedef unsigned long IOADDRESS;
 typedef unsigned long SISIOADDRESS;
@@ -118,7 +89,7 @@ typedef IOADDRESS SISIOADDRESS;
 #endif
 #endif
 
-enum _SIS_CHIP_TYPE {
+typedef enum _SIS_CHIP_TYPE {
     SIS_VGALegacy = 0,
     SIS_530,
     SIS_OLD,
@@ -128,115 +99,27 @@ enum _SIS_CHIP_TYPE {
     SIS_540,
     SIS_315H,   /* SiS 310 */
     SIS_315,
-    SIS_315PRO,
+    SIS_315PRO, /* SiS 325 */
     SIS_550,
     SIS_650,
     SIS_740,
     SIS_330,
     SIS_661,
     SIS_741,
-    SIS_660,
+    SIS_670,
+    SIS_660 = 35,
     SIS_760,
     SIS_761,
-    SIS_340,
+    SIS_762,
+    SIS_770,
+    SIS_340 = 55,
+    SIS_341,
+    SIS_342,
+    XGI_20  = 75,
+    XGI_40,
     MAX_SIS_CHIP
-};
-
-#ifndef SIS_HW_INFO
-typedef struct _SIS_HW_INFO  SIS_HW_INFO, *PSIS_HW_INFO;
-
-struct _SIS_HW_INFO
-{
-#ifdef LINUX_XF86
-    PCITAG PciTag;              /* PCI Tag */
-#endif
-
-    UCHAR *pjVirtualRomBase;    /* ROM image */
-
-    BOOLEAN UseROM;             /* Use the ROM image if provided */
-
-#ifdef LINUX_KERNEL
-    UCHAR SISIOMEMTYPE *pjVideoMemoryAddress;
-                                /* base virtual memory address */
-                                 /* of Linear VGA memory */
-
-    ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
-#endif
-
-    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0; relocated) */
-
-    UCHAR  jChipType;            /* Used to Identify SiS Graphics Chip */
-                                 /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */
+} SIS_CHIP_TYPE;
 
-    UCHAR  jChipRevision;        /* Used to Identify SiS Graphics Chip Revision */
-
-    BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
-};
-#endif
-
-/* Addtional IOCTLs for communication sisfb <> X driver        */
-/* If changing this, sisfb.h must also be changed (for sisfb) */
-
-#ifdef LINUX_XF86  /* We don't want the X driver to depend on the kernel source */
-
-/* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_SIZE    0x8004f300
-#define SISFB_GET_INFO         0x8000f301  /* Must be patched with result from ..._SIZE at D[29:16] */
-/* deprecated ioctl number (for older versions of sisfb) */
-#define SISFB_GET_INFO_OLD     0x80046ef8
-
-/* ioctls for tv parameters (position) */
-#define SISFB_SET_TVPOSOFFSET   0x4004f304
-
-/* lock sisfb from register access */
-#define SISFB_SET_LOCK         0x4004f306
-
-/* Structure argument for SISFB_GET_INFO ioctl  */
-typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
-
-struct _SISFB_INFO {
-       CARD32  sisfb_id;               /* for identifying sisfb */
-#ifndef SISFB_ID
-#define SISFB_ID         0x53495346    /* Identify myself with 'SISF' */
-#endif
-       CARD32  chip_id;                /* PCI ID of detected chip */
-       CARD32  memory;                 /* video memory in KB which sisfb manages */
-       CARD32  heapstart;              /* heap start (= sisfb "mem" argument) in KB */
-       CARD8   fbvidmode;              /* current sisfb mode */
-
-       CARD8   sisfb_version;
-       CARD8   sisfb_revision;
-       CARD8   sisfb_patchlevel;
-
-       CARD8   sisfb_caps;             /* sisfb's capabilities */
-
-       CARD32  sisfb_tqlen;            /* turbo queue length (in KB) */
-
-       CARD32  sisfb_pcibus;           /* The card's PCI ID */
-       CARD32  sisfb_pcislot;
-       CARD32  sisfb_pcifunc;
-
-       CARD8   sisfb_lcdpdc;
-
-       CARD8   sisfb_lcda;
-
-       CARD32  sisfb_vbflags;
-       CARD32  sisfb_currentvbflags;
-
-       CARD32  sisfb_scalelcd;
-       CARD32  sisfb_specialtiming;
-
-       CARD8   sisfb_haveemi;
-       CARD8   sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-       CARD8   sisfb_haveemilcd;
-
-       CARD8   sisfb_lcdpdca;
-
-       CARD16  sisfb_tvxpos, sisfb_tvypos;     /* Warning: Values + 32 ! */
-
-       CARD8 reserved[208];                    /* for future use */
-};
-#endif
 
 #endif
 
index d4d55c98bce6e8f91b39d8ae2be847246c51c23c..9ae32923c142d08fdc3721f7ee9eda6bf71bf66a 100644 (file)
@@ -3,7 +3,7 @@
 /*
  * General structure definitions for universal mode switching modules
  *
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
  *
  * If distributed as part of the Linux kernel, the following license terms
  * apply:
  *
  */
 
-#ifndef _VSTRUCT_
-#define _VSTRUCT_
-
-typedef struct _SiS_PanelDelayTblStruct
-{
-       UCHAR timer[2];
-} SiS_PanelDelayTblStruct;
-
-typedef struct _SiS_LCDDataStruct
-{
-       USHORT RVBHCMAX;
-       USHORT RVBHCFACT;
-       USHORT VGAHT;
-       USHORT VGAVT;
-       USHORT LCDHT;
-       USHORT LCDVT;
-} SiS_LCDDataStruct;
-
-typedef struct _SiS_TVDataStruct
-{
-       USHORT RVBHCMAX;
-       USHORT RVBHCFACT;
-       USHORT VGAHT;
-       USHORT VGAVT;
-       USHORT TVHDE;
-       USHORT TVVDE;
-       USHORT RVBHRS;
-       UCHAR  FlickerMode;
-       USHORT HALFRVBHRS;
-       UCHAR  RY1COE;
-       UCHAR  RY2COE;
-       UCHAR  RY3COE;
-       UCHAR  RY4COE;
-} SiS_TVDataStruct;
-
-typedef struct _SiS_LVDSDataStruct
-{
-       USHORT VGAHT;
-       USHORT VGAVT;
-       USHORT LCDHT;
-       USHORT LCDVT;
-} SiS_LVDSDataStruct;
-
-typedef struct _SiS_LVDSDesStruct
-{
-       USHORT LCDHDES;
-       USHORT LCDVDES;
-} SiS_LVDSDesStruct;
-
-typedef struct _SiS_LVDSCRT1DataStruct
-{
-       UCHAR  CR[15];
-} SiS_LVDSCRT1DataStruct;
-
-typedef struct _SiS_LCDACRT1DataStruct
-{
-       UCHAR  CR[17];
-} SiS_LCDACRT1DataStruct;
-
-typedef struct _SiS_CHTVRegDataStruct
-{
-       UCHAR  Reg[16];
-} SiS_CHTVRegDataStruct;
-
-typedef struct _SiS_StStruct
-{
-       UCHAR  St_ModeID;
-       USHORT St_ModeFlag;
-       UCHAR  St_StTableIndex;
-       UCHAR  St_CRT2CRTC;
-       UCHAR  St_ResInfo;
-       UCHAR  VB_StTVFlickerIndex;
-       UCHAR  VB_StTVEdgeIndex;
-       UCHAR  VB_StTVYFilterIndex;
-       UCHAR  St_PDC;
-} SiS_StStruct;
-
-typedef struct _SiS_VBModeStruct
-{
-       UCHAR  ModeID;
-       UCHAR  VB_TVDelayIndex;
-       UCHAR  VB_TVFlickerIndex;
-       UCHAR  VB_TVPhaseIndex;
-       UCHAR  VB_TVYFilterIndex;
-       UCHAR  VB_LCDDelayIndex;
-       UCHAR  _VB_LCDHIndex;
-       UCHAR  _VB_LCDVIndex;
-} SiS_VBModeStruct;
-
-typedef struct _SiS_StandTableStruct
-{
-       UCHAR  CRT_COLS;
-       UCHAR  ROWS;
-       UCHAR  CHAR_HEIGHT;
-       USHORT CRT_LEN;
-       UCHAR  SR[4];
-       UCHAR  MISC;
-       UCHAR  CRTC[0x19];
-       UCHAR  ATTR[0x14];
-       UCHAR  GRC[9];
-} SiS_StandTableStruct;
-
-typedef struct _SiS_ExtStruct
-{
-       UCHAR  Ext_ModeID;
-       USHORT Ext_ModeFlag;
-       USHORT Ext_VESAID;
-       UCHAR  Ext_RESINFO;
-       UCHAR  VB_ExtTVFlickerIndex;
-       UCHAR  VB_ExtTVEdgeIndex;
-       UCHAR  VB_ExtTVYFilterIndex;
-       UCHAR  VB_ExtTVYFilterIndexROM661;
-       UCHAR  REFindex;
-       CHAR   ROMMODEIDX661;
-} SiS_ExtStruct;
-
-typedef struct _SiS_Ext2Struct
-{
-       USHORT Ext_InfoFlag;
-       UCHAR  Ext_CRT1CRTC;
-       UCHAR  Ext_CRTVCLK;
-       UCHAR  Ext_CRT2CRTC;
-       UCHAR  Ext_CRT2CRTC_NS;
-       UCHAR  ModeID;
-       USHORT XRes;
-       USHORT YRes;
-       UCHAR  Ext_PDC;
-} SiS_Ext2Struct;
-
-typedef struct _SiS_Part2PortTblStruct
-{
-       UCHAR  CR[12];
-} SiS_Part2PortTblStruct;
-
-typedef struct _SiS_CRT1TableStruct
-{
-       UCHAR  CR[17];
-} SiS_CRT1TableStruct;
-
-typedef struct _SiS_MCLKDataStruct
-{
-       UCHAR  SR28,SR29,SR2A;
-       USHORT CLOCK;
-} SiS_MCLKDataStruct;
-
-typedef struct _SiS_VCLKDataStruct
-{
-       UCHAR  SR2B,SR2C;
-       USHORT CLOCK;
-} SiS_VCLKDataStruct;
-
-typedef struct _SiS_VBVCLKDataStruct
-{
-       UCHAR  Part4_A,Part4_B;
-       USHORT CLOCK;
-} SiS_VBVCLKDataStruct;
-
-typedef struct _SiS_StResInfoStruct
-{
-       USHORT HTotal;
-       USHORT VTotal;
-} SiS_StResInfoStruct;
-
-typedef struct _SiS_ModeResInfoStruct
-{
-       USHORT HTotal;
-       USHORT VTotal;
-       UCHAR  XChar;
-       UCHAR  YChar;
-} SiS_ModeResInfoStruct;
-
-
-
-typedef UCHAR DRAM4Type[4];
+#ifndef _VSTRUCT_H_
+#define _VSTRUCT_H_
+
+struct SiS_PanelDelayTbl {
+       unsigned char timer[2];
+};
+
+struct SiS_LCDData {
+       unsigned short RVBHCMAX;
+       unsigned short RVBHCFACT;
+       unsigned short VGAHT;
+       unsigned short VGAVT;
+       unsigned short LCDHT;
+       unsigned short LCDVT;
+};
+
+struct SiS_TVData {
+       unsigned short RVBHCMAX;
+       unsigned short RVBHCFACT;
+       unsigned short VGAHT;
+       unsigned short VGAVT;
+       unsigned short TVHDE;
+       unsigned short TVVDE;
+       unsigned short RVBHRS;
+       unsigned char  FlickerMode;
+       unsigned short HALFRVBHRS;
+       unsigned short RVBHRS2;
+       unsigned char  RY1COE;
+       unsigned char  RY2COE;
+       unsigned char  RY3COE;
+       unsigned char  RY4COE;
+};
+
+struct SiS_LVDSData {
+       unsigned short VGAHT;
+       unsigned short VGAVT;
+       unsigned short LCDHT;
+       unsigned short LCDVT;
+};
+
+struct SiS_LVDSDes {
+       unsigned short LCDHDES;
+       unsigned short LCDVDES;
+};
+
+struct SiS_LVDSCRT1Data {
+       unsigned char  CR[15];
+};
+
+struct SiS_CHTVRegData {
+       unsigned char  Reg[16];
+};
+
+struct SiS_St {
+       unsigned char  St_ModeID;
+       unsigned short St_ModeFlag;
+       unsigned char  St_StTableIndex;
+       unsigned char  St_CRT2CRTC;
+       unsigned char  St_ResInfo;
+       unsigned char  VB_StTVFlickerIndex;
+       unsigned char  VB_StTVEdgeIndex;
+       unsigned char  VB_StTVYFilterIndex;
+       unsigned char  St_PDC;
+};
+
+struct SiS_VBMode {
+       unsigned char  ModeID;
+       unsigned char  VB_TVDelayIndex;
+       unsigned char  VB_TVFlickerIndex;
+       unsigned char  VB_TVPhaseIndex;
+       unsigned char  VB_TVYFilterIndex;
+       unsigned char  VB_LCDDelayIndex;
+       unsigned char  _VB_LCDHIndex;
+       unsigned char  _VB_LCDVIndex;
+};
+
+struct SiS_StandTable_S {
+       unsigned char  CRT_COLS;
+       unsigned char  ROWS;
+       unsigned char  CHAR_HEIGHT;
+       unsigned short CRT_LEN;
+       unsigned char  SR[4];
+       unsigned char  MISC;
+       unsigned char  CRTC[0x19];
+       unsigned char  ATTR[0x14];
+       unsigned char  GRC[9];
+};
+
+struct SiS_Ext {
+       unsigned char  Ext_ModeID;
+       unsigned short Ext_ModeFlag;
+       unsigned short Ext_VESAID;
+       unsigned char  Ext_RESINFO;
+       unsigned char  VB_ExtTVFlickerIndex;
+       unsigned char  VB_ExtTVEdgeIndex;
+       unsigned char  VB_ExtTVYFilterIndex;
+       unsigned char  VB_ExtTVYFilterIndexROM661;
+       unsigned char  REFindex;
+       char           ROMMODEIDX661;
+};
+
+struct SiS_Ext2 {
+       unsigned short Ext_InfoFlag;
+       unsigned char  Ext_CRT1CRTC;
+       unsigned char  Ext_CRTVCLK;
+       unsigned char  Ext_CRT2CRTC;
+       unsigned char  Ext_CRT2CRTC_NS;
+       unsigned char  ModeID;
+       unsigned short XRes;
+       unsigned short YRes;
+       unsigned char  Ext_PDC;
+       unsigned char  Ext_FakeCRT2CRTC;
+       unsigned char  Ext_FakeCRT2Clk;
+       unsigned char  Ext_CRT1CRTC_NORM;
+       unsigned char  Ext_CRTVCLK_NORM;
+       unsigned char  Ext_CRT1CRTC_WIDE;
+       unsigned char  Ext_CRTVCLK_WIDE;
+};
+
+struct SiS_Part2PortTbl {
+       unsigned char  CR[12];
+};
+
+struct SiS_CRT1Table {
+       unsigned char  CR[17];
+};
+
+struct SiS_MCLKData {
+       unsigned char  SR28,SR29,SR2A;
+       unsigned short CLOCK;
+};
+
+struct SiS_VCLKData {
+       unsigned char  SR2B,SR2C;
+       unsigned short CLOCK;
+};
+
+struct SiS_VBVCLKData {
+       unsigned char  Part4_A,Part4_B;
+       unsigned short CLOCK;
+};
+
+struct SiS_StResInfo_S {
+       unsigned short HTotal;
+       unsigned short VTotal;
+};
+
+struct SiS_ModeResInfo_S {
+       unsigned short HTotal;
+       unsigned short VTotal;
+       unsigned char  XChar;
+       unsigned char  YChar;
+};
 
 /* Defines for SiS_CustomT */
 /* Never change these for sisfb compatibility */
-#define CUT_NONE          0
-#define CUT_FORCENONE     1
-#define CUT_BARCO1366     2
-#define CUT_BARCO1024     3
-#define CUT_COMPAQ1280    4
-#define CUT_COMPAQ12802   5
-#define CUT_PANEL848      6
-#define CUT_CLEVO1024     7
-#define CUT_CLEVO10242    8
-#define CUT_CLEVO1400     9
-#define CUT_CLEVO14002    10
-#define CUT_UNIWILL1024   11
-#define CUT_ASUSL3000D    12
-#define CUT_UNIWILL10242  13
-#define CUT_ACER1280      14
-#define CUT_COMPAL1400_1  15
-#define CUT_COMPAL1400_2  16
-#define CUT_ASUSA2H_1     17
-#define CUT_ASUSA2H_2     18
-
-typedef struct _SiS_Private
+#define CUT_NONE                0
+#define CUT_FORCENONE           1
+#define CUT_BARCO1366           2
+#define CUT_BARCO1024           3
+#define CUT_COMPAQ1280          4
+#define CUT_COMPAQ12802                 5
+#define CUT_PANEL848            6
+#define CUT_CLEVO1024           7
+#define CUT_CLEVO10242          8
+#define CUT_CLEVO1400           9
+#define CUT_CLEVO14002         10
+#define CUT_UNIWILL1024                11
+#define CUT_ASUSL3000D         12
+#define CUT_UNIWILL10242       13
+#define CUT_ACER1280           14
+#define CUT_COMPAL1400_1       15
+#define CUT_COMPAL1400_2       16
+#define CUT_ASUSA2H_1          17
+#define CUT_ASUSA2H_2          18
+#define CUT_UNKNOWNLCD         19
+#define CUT_AOP8060            20
+#define CUT_PANEL856           21
+
+struct SiS_Private
 {
-#ifdef LINUX_KERNEL
-        SISIOADDRESS RelIO;
+       unsigned char                   ChipType;
+       unsigned char                   ChipRevision;
+#ifdef SIS_XORG_XF86
+       PCITAG                          PciTag;
 #endif
-       SISIOADDRESS SiS_P3c4;
-       SISIOADDRESS SiS_P3d4;
-       SISIOADDRESS SiS_P3c0;
-       SISIOADDRESS SiS_P3ce;
-       SISIOADDRESS SiS_P3c2;
-       SISIOADDRESS SiS_P3ca;
-       SISIOADDRESS SiS_P3c6;
-       SISIOADDRESS SiS_P3c7;
-       SISIOADDRESS SiS_P3c8;
-       SISIOADDRESS SiS_P3c9;
-       SISIOADDRESS SiS_P3cb;
-       SISIOADDRESS SiS_P3cd;
-       SISIOADDRESS SiS_P3da;
-       SISIOADDRESS SiS_Part1Port;
-       SISIOADDRESS SiS_Part2Port;
-       SISIOADDRESS SiS_Part3Port;
-       SISIOADDRESS SiS_Part4Port;
-       SISIOADDRESS SiS_Part5Port;
-       SISIOADDRESS SiS_VidCapt;
-       SISIOADDRESS SiS_VidPlay;
-       USHORT SiS_IF_DEF_LVDS;
-       USHORT SiS_IF_DEF_CH70xx;
-       USHORT SiS_IF_DEF_CONEX;
-       USHORT SiS_IF_DEF_TRUMPION;
-       USHORT SiS_IF_DEF_DSTN;
-       USHORT SiS_IF_DEF_FSTN;
-       USHORT SiS_SysFlags;
-       UCHAR  SiS_VGAINFO;
-#ifdef LINUX_XF86
-        USHORT SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
+#ifdef SIS_LINUX_KERNEL
+       void                            *ivideo;
 #endif
-       BOOLEAN SiS_UseROM;
-       BOOLEAN SiS_ROMNew;
-       BOOLEAN SiS_NeedRomModeData;
-       BOOLEAN PanelSelfDetected;
-       int     SiS_CHOverScan;
-       BOOLEAN SiS_CHSOverScan;
-       BOOLEAN SiS_ChSW;
-       BOOLEAN SiS_UseLCDA;
-       int     SiS_UseOEM;
-       ULONG   SiS_CustomT;
-       USHORT  SiS_Backup70xx;
-       BOOLEAN HaveEMI;
-       BOOLEAN HaveEMILCD;
-       BOOLEAN OverruleEMI;
-       UCHAR  EMI_30,EMI_31,EMI_32,EMI_33;
-       USHORT SiS_EMIOffset;
-       SHORT  PDC, PDCA;
-       UCHAR  SiS_MyCR63;
-       USHORT SiS_CRT1Mode;
-       USHORT SiS_flag_clearbuffer;
-       int    SiS_RAMType;
-       UCHAR  SiS_ChannelAB;
-       UCHAR  SiS_DataBusWidth;
-       USHORT SiS_ModeType;
-       USHORT SiS_VBInfo;
-       USHORT SiS_TVMode;
-       USHORT SiS_LCDResInfo;
-       USHORT SiS_LCDTypeInfo;
-       USHORT SiS_LCDInfo;
-       USHORT SiS_LCDInfo661;
-       USHORT SiS_VBType;
-       USHORT SiS_VBExtInfo;
-       USHORT SiS_YPbPr;
-       USHORT SiS_SelectCRT2Rate;
-       USHORT SiS_SetFlag;
-       USHORT SiS_RVBHCFACT;
-       USHORT SiS_RVBHCMAX;
-       USHORT SiS_RVBHRS;
-       USHORT SiS_VGAVT;
-       USHORT SiS_VGAHT;
-       USHORT SiS_VT;
-       USHORT SiS_HT;
-       USHORT SiS_VGAVDE;
-       USHORT SiS_VGAHDE;
-       USHORT SiS_VDE;
-       USHORT SiS_HDE;
-       USHORT SiS_NewFlickerMode;
-       USHORT SiS_RY1COE;
-       USHORT SiS_RY2COE;
-       USHORT SiS_RY3COE;
-       USHORT SiS_RY4COE;
-       USHORT SiS_LCDHDES;
-       USHORT SiS_LCDVDES;
-       USHORT SiS_DDC_Port;
-       USHORT SiS_DDC_Index;
-       USHORT SiS_DDC_Data;
-       USHORT SiS_DDC_NData;
-       USHORT SiS_DDC_Clk;
-       USHORT SiS_DDC_NClk;
-       USHORT SiS_DDC_DeviceAddr;
-       USHORT SiS_DDC_ReadAddr;
-       USHORT SiS_DDC_SecAddr;
-       USHORT SiS_ChrontelInit;
-       BOOLEAN SiS_SensibleSR11;
-       USHORT SiS661LCD2TableSize;
-
-       USHORT SiS_PanelMinLVDS;
-       USHORT SiS_PanelMin301;
-
-       const SiS_StStruct          *SiS_SModeIDTable;
-       const SiS_StandTableStruct  *SiS_StandTable;
-       const SiS_ExtStruct         *SiS_EModeIDTable;
-       const SiS_Ext2Struct        *SiS_RefIndex;
-       const SiS_VBModeStruct      *SiS_VBModeIDTable;
-       const SiS_CRT1TableStruct   *SiS_CRT1Table;
-       const SiS_MCLKDataStruct    *SiS_MCLKData_0;
-       const SiS_MCLKDataStruct    *SiS_MCLKData_1;
-       SiS_VCLKDataStruct          *SiS_VCLKData;
-       SiS_VBVCLKDataStruct        *SiS_VBVCLKData;
-       const SiS_StResInfoStruct   *SiS_StResInfo;
-       const SiS_ModeResInfoStruct *SiS_ModeResInfo;
-
-       const UCHAR                 *pSiS_OutputSelect;
-       const UCHAR                 *pSiS_SoftSetting;
-
-       const DRAM4Type *SiS_SR15; /* pointer : point to array */
-#ifdef LINUX_KERNEL
-       UCHAR *pSiS_SR07;
-       const DRAM4Type *SiS_CR40; /* pointer : point to array */
-       UCHAR *SiS_CR49;
-       UCHAR *SiS_SR25;
-       UCHAR *pSiS_SR1F;
-       UCHAR *pSiS_SR21;
-       UCHAR *pSiS_SR22;
-       UCHAR *pSiS_SR23;
-       UCHAR *pSiS_SR24;
-       UCHAR *pSiS_SR31;
-       UCHAR *pSiS_SR32;
-       UCHAR *pSiS_SR33;
-       UCHAR *pSiS_CRT2Data_1_2;
-       UCHAR *pSiS_CRT2Data_4_D;
-       UCHAR *pSiS_CRT2Data_4_E;
-       UCHAR *pSiS_CRT2Data_4_10;
-       const USHORT *pSiS_RGBSenseData;
-       const USHORT *pSiS_VideoSenseData;
-       const USHORT *pSiS_YCSenseData;
-       const USHORT *pSiS_RGBSenseData2;
-       const USHORT *pSiS_VideoSenseData2;
-       const USHORT *pSiS_YCSenseData2;
+       unsigned char                   *VirtualRomBase;
+       BOOLEAN                         UseROM;
+#ifdef SIS_LINUX_KERNEL
+       unsigned char SISIOMEMTYPE      *VideoMemoryAddress;
+       unsigned int                    VideoMemorySize;
 #endif
+       SISIOADDRESS                    IOAddress;
+       SISIOADDRESS                    IOAddress2;  /* For dual chip XGI volari */
 
-       const SiS_PanelDelayTblStruct *SiS_PanelDelayTbl;
-       const SiS_PanelDelayTblStruct *SiS_PanelDelayTblLVDS;
+#ifdef SIS_LINUX_KERNEL
+       SISIOADDRESS                    RelIO;
+#endif
+       SISIOADDRESS                    SiS_P3c4;
+       SISIOADDRESS                    SiS_P3d4;
+       SISIOADDRESS                    SiS_P3c0;
+       SISIOADDRESS                    SiS_P3ce;
+       SISIOADDRESS                    SiS_P3c2;
+       SISIOADDRESS                    SiS_P3ca;
+       SISIOADDRESS                    SiS_P3c6;
+       SISIOADDRESS                    SiS_P3c7;
+       SISIOADDRESS                    SiS_P3c8;
+       SISIOADDRESS                    SiS_P3c9;
+       SISIOADDRESS                    SiS_P3cb;
+       SISIOADDRESS                    SiS_P3cc;
+       SISIOADDRESS                    SiS_P3cd;
+       SISIOADDRESS                    SiS_P3da;
+       SISIOADDRESS                    SiS_Part1Port;
+       SISIOADDRESS                    SiS_Part2Port;
+       SISIOADDRESS                    SiS_Part3Port;
+       SISIOADDRESS                    SiS_Part4Port;
+       SISIOADDRESS                    SiS_Part5Port;
+       SISIOADDRESS                    SiS_VidCapt;
+       SISIOADDRESS                    SiS_VidPlay;
+       unsigned short                  SiS_IF_DEF_LVDS;
+       unsigned short                  SiS_IF_DEF_CH70xx;
+       unsigned short                  SiS_IF_DEF_CONEX;
+       unsigned short                  SiS_IF_DEF_TRUMPION;
+       unsigned short                  SiS_IF_DEF_DSTN;
+       unsigned short                  SiS_IF_DEF_FSTN;
+       unsigned short                  SiS_SysFlags;
+       unsigned char                   SiS_VGAINFO;
+#ifdef SIS_XORG_XF86
+       unsigned short                  SiS_CP1, SiS_CP2, SiS_CP3, SiS_CP4;
+#endif
+       BOOLEAN                         SiS_UseROM;
+       BOOLEAN                         SiS_ROMNew;
+       BOOLEAN                         SiS_XGIROM;
+       BOOLEAN                         SiS_NeedRomModeData;
+       BOOLEAN                         PanelSelfDetected;
+       BOOLEAN                         DDCPortMixup;
+       int                             SiS_CHOverScan;
+       BOOLEAN                         SiS_CHSOverScan;
+       BOOLEAN                         SiS_ChSW;
+       BOOLEAN                         SiS_UseLCDA;
+       int                             SiS_UseOEM;
+       unsigned int                    SiS_CustomT;
+       int                             SiS_UseWide, SiS_UseWideCRT2;
+       int                             SiS_TVBlue;
+       unsigned short                  SiS_Backup70xx;
+       BOOLEAN                         HaveEMI;
+       BOOLEAN                         HaveEMILCD;
+       BOOLEAN                         OverruleEMI;
+       unsigned char                   EMI_30,EMI_31,EMI_32,EMI_33;
+       unsigned short                  SiS_EMIOffset;
+       unsigned short                  SiS_PWDOffset;
+       short                           PDC, PDCA;
+       unsigned char                   SiS_MyCR63;
+       unsigned short                  SiS_CRT1Mode;
+       unsigned short                  SiS_flag_clearbuffer;
+       int                             SiS_RAMType;
+       unsigned char                   SiS_ChannelAB;
+       unsigned char                   SiS_DataBusWidth;
+       unsigned short                  SiS_ModeType;
+       unsigned short                  SiS_VBInfo;
+       unsigned short                  SiS_TVMode;
+       unsigned short                  SiS_LCDResInfo;
+       unsigned short                  SiS_LCDTypeInfo;
+       unsigned short                  SiS_LCDInfo;
+       unsigned short                  SiS_LCDInfo661;
+       unsigned short                  SiS_VBType;
+       unsigned short                  SiS_VBExtInfo;
+       unsigned short                  SiS_YPbPr;
+       unsigned short                  SiS_SelectCRT2Rate;
+       unsigned short                  SiS_SetFlag;
+       unsigned short                  SiS_RVBHCFACT;
+       unsigned short                  SiS_RVBHCMAX;
+       unsigned short                  SiS_RVBHRS;
+       unsigned short                  SiS_RVBHRS2;
+       unsigned short                  SiS_VGAVT;
+       unsigned short                  SiS_VGAHT;
+       unsigned short                  SiS_VT;
+       unsigned short                  SiS_HT;
+       unsigned short                  SiS_VGAVDE;
+       unsigned short                  SiS_VGAHDE;
+       unsigned short                  SiS_VDE;
+       unsigned short                  SiS_HDE;
+       unsigned short                  SiS_NewFlickerMode;
+       unsigned short                  SiS_RY1COE;
+       unsigned short                  SiS_RY2COE;
+       unsigned short                  SiS_RY3COE;
+       unsigned short                  SiS_RY4COE;
+       unsigned short                  SiS_LCDHDES;
+       unsigned short                  SiS_LCDVDES;
+       unsigned short                  SiS_DDC_Port;
+       unsigned short                  SiS_DDC_Index;
+       unsigned short                  SiS_DDC_Data;
+       unsigned short                  SiS_DDC_NData;
+       unsigned short                  SiS_DDC_Clk;
+       unsigned short                  SiS_DDC_NClk;
+       unsigned short                  SiS_DDC_DeviceAddr;
+       unsigned short                  SiS_DDC_ReadAddr;
+       unsigned short                  SiS_DDC_SecAddr;
+       unsigned short                  SiS_ChrontelInit;
+       BOOLEAN                         SiS_SensibleSR11;
+       unsigned short                  SiS661LCD2TableSize;
+
+       unsigned short                  SiS_PanelMinLVDS;
+       unsigned short                  SiS_PanelMin301;
+
+       const struct SiS_St             *SiS_SModeIDTable;
+       const struct SiS_StandTable_S   *SiS_StandTable;
+       const struct SiS_Ext            *SiS_EModeIDTable;
+       const struct SiS_Ext2           *SiS_RefIndex;
+       const struct SiS_VBMode         *SiS_VBModeIDTable;
+       const struct SiS_CRT1Table      *SiS_CRT1Table;
+       const struct SiS_MCLKData       *SiS_MCLKData_0;
+       const struct SiS_MCLKData       *SiS_MCLKData_1;
+       struct SiS_VCLKData             *SiS_VCLKData;
+       struct SiS_VBVCLKData           *SiS_VBVCLKData;
+       const struct SiS_StResInfo_S    *SiS_StResInfo;
+       const struct SiS_ModeResInfo_S  *SiS_ModeResInfo;
+
+       const unsigned char             *pSiS_OutputSelect;
+       const unsigned char             *pSiS_SoftSetting;
+
+       const unsigned char             *SiS_SR15;
+
+       const struct SiS_PanelDelayTbl  *SiS_PanelDelayTbl;
+       const struct SiS_PanelDelayTbl  *SiS_PanelDelayTblLVDS;
 
        /* SiS bridge */
 
-       const UCHAR *SiS_NTSCPhase;
-       const UCHAR *SiS_PALPhase;
-       const UCHAR *SiS_NTSCPhase2;
-       const UCHAR *SiS_PALPhase2;
-       const UCHAR *SiS_PALMPhase;
-       const UCHAR *SiS_PALNPhase;
-       const UCHAR *SiS_PALMPhase2;
-       const UCHAR *SiS_PALNPhase2;
-       const UCHAR *SiS_SpecialPhase;
-       const UCHAR *SiS_SpecialPhaseM;
-       const UCHAR *SiS_SpecialPhaseJ;
-       const SiS_LCDDataStruct  *SiS_ExtLCD1024x768Data;
-       const SiS_LCDDataStruct  *SiS_St2LCD1024x768Data;
-       const SiS_LCDDataStruct  *SiS_LCD1280x720Data;
-       const SiS_LCDDataStruct  *SiS_StLCD1280x768_2Data;
-       const SiS_LCDDataStruct  *SiS_ExtLCD1280x768_2Data;
-       const SiS_LCDDataStruct  *SiS_LCD1280x800Data;
-       const SiS_LCDDataStruct  *SiS_LCD1280x800_2Data;
-       const SiS_LCDDataStruct  *SiS_LCD1280x960Data;
-       const SiS_LCDDataStruct  *SiS_ExtLCD1280x1024Data;
-       const SiS_LCDDataStruct  *SiS_St2LCD1280x1024Data;
-       const SiS_LCDDataStruct  *SiS_StLCD1400x1050Data;
-       const SiS_LCDDataStruct  *SiS_ExtLCD1400x1050Data;
-       const SiS_LCDDataStruct  *SiS_StLCD1600x1200Data;
-       const SiS_LCDDataStruct  *SiS_ExtLCD1600x1200Data;
-       const SiS_LCDDataStruct  *SiS_LCD1680x1050Data;
-       const SiS_LCDDataStruct  *SiS_NoScaleData;
-       const SiS_TVDataStruct   *SiS_StPALData;
-       const SiS_TVDataStruct   *SiS_ExtPALData;
-       const SiS_TVDataStruct   *SiS_StNTSCData;
-       const SiS_TVDataStruct   *SiS_ExtNTSCData;
-       const SiS_TVDataStruct   *SiS_St1HiTVData;
-       const SiS_TVDataStruct   *SiS_St2HiTVData;
-       const SiS_TVDataStruct   *SiS_ExtHiTVData;
-       const SiS_TVDataStruct   *SiS_St525iData;
-       const SiS_TVDataStruct   *SiS_St525pData;
-       const SiS_TVDataStruct   *SiS_St750pData;
-       const SiS_TVDataStruct   *SiS_Ext525iData;
-       const SiS_TVDataStruct   *SiS_Ext525pData;
-       const SiS_TVDataStruct   *SiS_Ext750pData;
-       const UCHAR *SiS_NTSCTiming;
-       const UCHAR *SiS_PALTiming;
-       const UCHAR *SiS_HiTVExtTiming;
-       const UCHAR *SiS_HiTVSt1Timing;
-       const UCHAR *SiS_HiTVSt2Timing;
-       const UCHAR *SiS_HiTVGroup3Data;
-       const UCHAR *SiS_HiTVGroup3Simu;
+       const struct SiS_LCDData        *SiS_ExtLCD1024x768Data;
+       const struct SiS_LCDData        *SiS_St2LCD1024x768Data;
+       const struct SiS_LCDData        *SiS_LCD1280x720Data;
+       const struct SiS_LCDData        *SiS_StLCD1280x768_2Data;
+       const struct SiS_LCDData        *SiS_ExtLCD1280x768_2Data;
+       const struct SiS_LCDData        *SiS_LCD1280x800Data;
+       const struct SiS_LCDData        *SiS_LCD1280x800_2Data;
+       const struct SiS_LCDData        *SiS_LCD1280x854Data;
+       const struct SiS_LCDData        *SiS_LCD1280x960Data;
+       const struct SiS_LCDData        *SiS_ExtLCD1280x1024Data;
+       const struct SiS_LCDData        *SiS_St2LCD1280x1024Data;
+       const struct SiS_LCDData        *SiS_StLCD1400x1050Data;
+       const struct SiS_LCDData        *SiS_ExtLCD1400x1050Data;
+       const struct SiS_LCDData        *SiS_StLCD1600x1200Data;
+       const struct SiS_LCDData        *SiS_ExtLCD1600x1200Data;
+       const struct SiS_LCDData        *SiS_LCD1680x1050Data;
+       const struct SiS_LCDData        *SiS_NoScaleData;
+       const struct SiS_TVData         *SiS_StPALData;
+       const struct SiS_TVData         *SiS_ExtPALData;
+       const struct SiS_TVData         *SiS_StNTSCData;
+       const struct SiS_TVData         *SiS_ExtNTSCData;
+       const struct SiS_TVData         *SiS_St1HiTVData;
+       const struct SiS_TVData         *SiS_St2HiTVData;
+       const struct SiS_TVData         *SiS_ExtHiTVData;
+       const struct SiS_TVData         *SiS_St525iData;
+       const struct SiS_TVData         *SiS_St525pData;
+       const struct SiS_TVData         *SiS_St750pData;
+       const struct SiS_TVData         *SiS_Ext525iData;
+       const struct SiS_TVData         *SiS_Ext525pData;
+       const struct SiS_TVData         *SiS_Ext750pData;
+       const unsigned char             *SiS_NTSCTiming;
+       const unsigned char             *SiS_PALTiming;
+       const unsigned char             *SiS_HiTVExtTiming;
+       const unsigned char             *SiS_HiTVSt1Timing;
+       const unsigned char             *SiS_HiTVSt2Timing;
+       const unsigned char             *SiS_HiTVGroup3Data;
+       const unsigned char             *SiS_HiTVGroup3Simu;
 #if 0
-       const UCHAR *SiS_HiTVTextTiming;
-       const UCHAR *SiS_HiTVGroup3Text;
+       const unsigned char             *SiS_HiTVTextTiming;
+       const unsigned char             *SiS_HiTVGroup3Text;
 #endif
 
-       const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_1;
-       const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_1;
-       const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_2;
-       const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_2;
-       const SiS_Part2PortTblStruct *SiS_CRT2Part2_1024x768_3;
-       const SiS_Part2PortTblStruct *SiS_CRT2Part2_1280x1024_3;
+       const struct SiS_Part2PortTbl   *SiS_CRT2Part2_1024x768_1;
+       const struct SiS_Part2PortTbl   *SiS_CRT2Part2_1024x768_2;
+       const struct SiS_Part2PortTbl   *SiS_CRT2Part2_1024x768_3;
 
        /* LVDS, Chrontel */
 
-       const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS800x600Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1024x768Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1024x768Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1280x1024Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1280x1024Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1280x960Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1280x960Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1400x1050Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1400x1050Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1600x1200Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1600x1200Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1280x768Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1280x768Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1024x600Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1024x600Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS1152x768Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS1152x768Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS640x480Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS320x480Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDSXXXxXXXData_1;
-       const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDSBARCO1366Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDSBARCO1024Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDSBARCO1024Data_2;
-       const SiS_LVDSDataStruct  *SiS_LVDS848x480Data_1;
-       const SiS_LVDSDataStruct  *SiS_LVDS848x480Data_2;
-       const SiS_LVDSDataStruct  *SiS_CHTVUNTSCData;
-       const SiS_LVDSDataStruct  *SiS_CHTVONTSCData;
-       const SiS_LVDSDataStruct  *SiS_CHTVUPALData;
-       const SiS_LVDSDataStruct  *SiS_CHTVOPALData;
-       const SiS_LVDSDataStruct  *SiS_CHTVUPALMData;
-       const SiS_LVDSDataStruct  *SiS_CHTVOPALMData;
-       const SiS_LVDSDataStruct  *SiS_CHTVUPALNData;
-       const SiS_LVDSDataStruct  *SiS_CHTVOPALNData;
-       const SiS_LVDSDataStruct  *SiS_CHTVSOPALData;
-
-       const SiS_LVDSDesStruct  *SiS_PanelType00_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType01_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType02_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType03_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType04_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType05_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType06_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType07_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType08_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType09_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType0a_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType0b_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType0c_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType0d_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType0e_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType0f_1;
-       const SiS_LVDSDesStruct  *SiS_PanelTypeNS_1;
-       const SiS_LVDSDesStruct  *SiS_PanelType00_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType01_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType02_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType03_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType04_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType05_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType06_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType07_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType08_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType09_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType0a_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType0b_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType0c_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType0d_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType0e_2;
-       const SiS_LVDSDesStruct  *SiS_PanelType0f_2;
-       const SiS_LVDSDesStruct  *SiS_PanelTypeNS_2;
-       const SiS_LVDSDesStruct  *SiS_CHTVUNTSCDesData;
-       const SiS_LVDSDesStruct  *SiS_CHTVONTSCDesData;
-       const SiS_LVDSDesStruct  *SiS_CHTVUPALDesData;
-       const SiS_LVDSDesStruct  *SiS_CHTVOPALDesData;
-
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11400x1050_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x768_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x600_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11152x768_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11600x1200_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11400x1050_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x768_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x600_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11152x768_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11600x1200_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11400x1050_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x768_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x600_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11152x768_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11600x1200_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1800x600_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x768_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x1024_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11400x1050_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11280x768_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11024x600_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11152x768_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT11600x1200_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1XXXxXXX_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1XXXxXXX_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_1_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_2;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_2_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1640x480_3_H;
-       const SiS_LVDSCRT1DataStruct  *SiS_LVDSCRT1320x480_1;
-       const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UNTSC;
-       const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1ONTSC;
-       const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1UPAL;
-       const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1OPAL;
-       const SiS_LVDSCRT1DataStruct  *SiS_CHTVCRT1SOPAL;
-
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_UNTSC;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_ONTSC;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPAL;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPAL;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALM;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALM;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_UPALN;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_OPALN;
-       const SiS_CHTVRegDataStruct *SiS_CHTVReg_SOPAL;
-
-       const UCHAR *SiS_CHTVVCLKUNTSC;
-       const UCHAR *SiS_CHTVVCLKONTSC;
-       const UCHAR *SiS_CHTVVCLKUPAL;
-       const UCHAR *SiS_CHTVVCLKOPAL;
-       const UCHAR *SiS_CHTVVCLKUPALM;
-       const UCHAR *SiS_CHTVVCLKOPALM;
-       const UCHAR *SiS_CHTVVCLKUPALN;
-       const UCHAR *SiS_CHTVVCLKOPALN;
-       const UCHAR *SiS_CHTVVCLKSOPAL;
-
-       USHORT  PanelXRes, PanelHT;
-       USHORT  PanelYRes, PanelVT;
-       USHORT  PanelHRS,  PanelHRE;
-       USHORT  PanelVRS,  PanelVRE;
-       USHORT  PanelVCLKIdx300;
-       USHORT  PanelVCLKIdx315;
-
-       BOOLEAN UseCustomMode;
-       BOOLEAN CRT1UsesCustomMode;
-       USHORT  CHDisplay;
-       USHORT  CHSyncStart;
-       USHORT  CHSyncEnd;
-       USHORT  CHTotal;
-       USHORT  CHBlankStart;
-       USHORT  CHBlankEnd;
-       USHORT  CVDisplay;
-       USHORT  CVSyncStart;
-       USHORT  CVSyncEnd;
-       USHORT  CVTotal;
-       USHORT  CVBlankStart;
-       USHORT  CVBlankEnd;
-       ULONG   CDClock;
-       ULONG   CFlags;   
-       UCHAR   CCRT1CRTC[17];
-       UCHAR   CSR2B;
-       UCHAR   CSR2C;
-       USHORT  CSRClock;
-       USHORT  CSRClock_CRT1;
-       USHORT  CModeFlag;
-       USHORT  CModeFlag_CRT1;
-       USHORT  CInfoFlag;
-
-       int     LVDSHL;
-       
-       BOOLEAN Backup;
-       UCHAR Backup_Mode;
-       UCHAR Backup_14;
-       UCHAR Backup_15;
-       UCHAR Backup_16;
-       UCHAR Backup_17;
-       UCHAR Backup_18;
-       UCHAR Backup_19;
-       UCHAR Backup_1a;
-       UCHAR Backup_1b;
-       UCHAR Backup_1c;
-       UCHAR Backup_1d;
-       
-       int     UsePanelScaler;
-       int     CenterScreen;
-
-       USHORT  CP_Vendor, CP_Product;
-       BOOLEAN CP_HaveCustomData;
-       int     CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
-       int     CP_MaxX, CP_MaxY, CP_MaxClock;
-       UCHAR   CP_PrefSR2B, CP_PrefSR2C;
-       USHORT  CP_PrefClock;
-       BOOLEAN CP_Supports64048075;
-       int     CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
-       int     CP_HTotal[7], CP_VTotal[7];
-       int     CP_HSyncStart[7], CP_VSyncStart[7];
-       int     CP_HSyncEnd[7], CP_VSyncEnd[7];
-       int     CP_HBlankStart[7], CP_VBlankStart[7];
-       int     CP_HBlankEnd[7], CP_VBlankEnd[7];
-       int     CP_Clock[7];
-       BOOLEAN CP_DataValid[7];
-       BOOLEAN CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
-} SiS_Private;
+       const struct SiS_LVDSData       *SiS_LVDS320x240Data_1;
+       const struct SiS_LVDSData       *SiS_LVDS320x240Data_2;
+       const struct SiS_LVDSData       *SiS_LVDS640x480Data_1;
+       const struct SiS_LVDSData       *SiS_LVDS800x600Data_1;
+       const struct SiS_LVDSData       *SiS_LVDS1024x600Data_1;
+       const struct SiS_LVDSData       *SiS_LVDS1024x768Data_1;
+       const struct SiS_LVDSData       *SiS_LVDSBARCO1366Data_1;
+       const struct SiS_LVDSData       *SiS_LVDSBARCO1366Data_2;
+       const struct SiS_LVDSData       *SiS_LVDSBARCO1024Data_1;
+       const struct SiS_LVDSData       *SiS_LVDS848x480Data_1;
+       const struct SiS_LVDSData       *SiS_LVDS848x480Data_2;
+       const struct SiS_LVDSData       *SiS_CHTVUNTSCData;
+       const struct SiS_LVDSData       *SiS_CHTVONTSCData;
+       const struct SiS_LVDSData       *SiS_CHTVUPALData;
+       const struct SiS_LVDSData       *SiS_CHTVOPALData;
+       const struct SiS_LVDSData       *SiS_CHTVUPALMData;
+       const struct SiS_LVDSData       *SiS_CHTVOPALMData;
+       const struct SiS_LVDSData       *SiS_CHTVUPALNData;
+       const struct SiS_LVDSData       *SiS_CHTVOPALNData;
+       const struct SiS_LVDSData       *SiS_CHTVSOPALData;
+
+       const struct SiS_LVDSDes        *SiS_PanelType04_1a;
+       const struct SiS_LVDSDes        *SiS_PanelType04_2a;
+       const struct SiS_LVDSDes        *SiS_PanelType04_1b;
+       const struct SiS_LVDSDes        *SiS_PanelType04_2b;
+
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1320x240_1;
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1320x240_2;
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1320x240_2_H;
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1320x240_3;
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1320x240_3_H;
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1640x480_1;
+       const struct SiS_LVDSCRT1Data   *SiS_LVDSCRT1640x480_1_H;
+       const struct SiS_LVDSCRT1Data   *SiS_CHTVCRT1UNTSC;
+       const struct SiS_LVDSCRT1Data   *SiS_CHTVCRT1ONTSC;
+       const struct SiS_LVDSCRT1Data   *SiS_CHTVCRT1UPAL;
+       const struct SiS_LVDSCRT1Data   *SiS_CHTVCRT1OPAL;
+       const struct SiS_LVDSCRT1Data   *SiS_CHTVCRT1SOPAL;
+
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_UNTSC;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_ONTSC;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_UPAL;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_OPAL;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_UPALM;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_OPALM;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_UPALN;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_OPALN;
+       const struct SiS_CHTVRegData    *SiS_CHTVReg_SOPAL;
+
+       const unsigned char             *SiS_CHTVVCLKUNTSC;
+       const unsigned char             *SiS_CHTVVCLKONTSC;
+       const unsigned char             *SiS_CHTVVCLKUPAL;
+       const unsigned char             *SiS_CHTVVCLKOPAL;
+       const unsigned char             *SiS_CHTVVCLKUPALM;
+       const unsigned char             *SiS_CHTVVCLKOPALM;
+       const unsigned char             *SiS_CHTVVCLKUPALN;
+       const unsigned char             *SiS_CHTVVCLKOPALN;
+       const unsigned char             *SiS_CHTVVCLKSOPAL;
+
+       unsigned short                  PanelXRes, PanelHT;
+       unsigned short                  PanelYRes, PanelVT;
+       unsigned short                  PanelHRS,  PanelHRE;
+       unsigned short                  PanelVRS,  PanelVRE;
+       unsigned short                  PanelVCLKIdx300;
+       unsigned short                  PanelVCLKIdx315;
+       BOOLEAN                         Alternate1600x1200;
+
+       BOOLEAN                         UseCustomMode;
+       BOOLEAN                         CRT1UsesCustomMode;
+       unsigned short                  CHDisplay;
+       unsigned short                  CHSyncStart;
+       unsigned short                  CHSyncEnd;
+       unsigned short                  CHTotal;
+       unsigned short                  CHBlankStart;
+       unsigned short                  CHBlankEnd;
+       unsigned short                  CVDisplay;
+       unsigned short                  CVSyncStart;
+       unsigned short                  CVSyncEnd;
+       unsigned short                  CVTotal;
+       unsigned short                  CVBlankStart;
+       unsigned short                  CVBlankEnd;
+       unsigned int                    CDClock;
+       unsigned int                    CFlags;
+       unsigned char                   CCRT1CRTC[17];
+       unsigned char                   CSR2B;
+       unsigned char                   CSR2C;
+       unsigned short                  CSRClock;
+       unsigned short                  CSRClock_CRT1;
+       unsigned short                  CModeFlag;
+       unsigned short                  CModeFlag_CRT1;
+       unsigned short                  CInfoFlag;
+
+       int                             LVDSHL;
+
+       BOOLEAN                         Backup;
+       unsigned char                   Backup_Mode;
+       unsigned char                   Backup_14;
+       unsigned char                   Backup_15;
+       unsigned char                   Backup_16;
+       unsigned char                   Backup_17;
+       unsigned char                   Backup_18;
+       unsigned char                   Backup_19;
+       unsigned char                   Backup_1a;
+       unsigned char                   Backup_1b;
+       unsigned char                   Backup_1c;
+       unsigned char                   Backup_1d;
+
+       unsigned char                   Init_P4_0E;
+
+       int                             UsePanelScaler;
+       int                             CenterScreen;
+
+       unsigned short                  CP_Vendor, CP_Product;
+       BOOLEAN                         CP_HaveCustomData;
+       int                             CP_PreferredX, CP_PreferredY, CP_PreferredIndex;
+       int                             CP_MaxX, CP_MaxY, CP_MaxClock;
+       unsigned char                   CP_PrefSR2B, CP_PrefSR2C;
+       unsigned short                  CP_PrefClock;
+       BOOLEAN                         CP_Supports64048075;
+       int                             CP_HDisplay[7], CP_VDisplay[7]; /* For Custom LCD panel dimensions */
+       int                             CP_HTotal[7], CP_VTotal[7];
+       int                             CP_HSyncStart[7], CP_VSyncStart[7];
+       int                             CP_HSyncEnd[7], CP_VSyncEnd[7];
+       int                             CP_HBlankStart[7], CP_VBlankStart[7];
+       int                             CP_HBlankEnd[7], CP_VBlankEnd[7];
+       int                             CP_Clock[7];
+       BOOLEAN                         CP_DataValid[7];
+       BOOLEAN                         CP_HSync_P[7], CP_VSync_P[7], CP_SyncValid[7];
+};
 
 #endif
 
index 698ca9232e73649c7669887685edca5e89b16698..81a6d9f188cf76ea4fb0020f71f6b75fc027c7f8 100644 (file)
@@ -1061,6 +1061,11 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
 
        chip_id = id->device;
 
+       if(chip_id == CYBERBLADEi1)
+               output("*** Please do use cyblafb, Cyberblade/i1 support "
+                      "will soon be removed from tridentfb!\n");
+
+
        /* If PCI id is 0x9660 then further detect chip type */
        
        if (chip_id == TGUI9660) {
index a272592b037391858ab28d31ad93171fc15be1bb..1ca80264c7b00a13036f887e4438ab052ca68fd5 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/fb.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <video/vga.h>
 #include <asm/io.h>
 #include <asm/mtrr.h>
 
@@ -54,6 +55,7 @@ static unsigned short  *pmi_base  = NULL;
 static void            (*pmi_start)(void);
 static void            (*pmi_pal)(void);
 static int             depth;
+static int             vga_compat;
 
 /* --------------------------------------------------------------------- */
 
@@ -86,6 +88,37 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
        return 0;
 }
 
+static int vesafb_blank(int blank, struct fb_info *info)
+{
+       int err = 1;
+
+       if (vga_compat) {
+               int loop = 10000;
+               u8 seq = 0, crtc17 = 0;
+
+               err = 0;
+
+               if (blank) {
+                       seq = 0x20;
+                       crtc17 = 0x00;
+               } else {
+                       seq = 0x00;
+                       crtc17 = 0x80;
+               }
+
+               vga_wseq(NULL, 0x00, 0x01);
+               seq |= vga_rseq(NULL, 0x01) & ~0x20;
+               vga_wseq(NULL, 0x00, seq);
+
+               crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
+               while (loop--);
+               vga_wcrt(NULL, 0x17, crtc17);
+               vga_wseq(NULL, 0x00, 0x03);
+       }
+
+       return err;
+}
+
 static void vesa_setpalette(int regno, unsigned red, unsigned green,
                            unsigned blue)
 {
@@ -176,6 +209,7 @@ static struct fb_ops vesafb_ops = {
        .owner          = THIS_MODULE,
        .fb_setcolreg   = vesafb_setcolreg,
        .fb_pan_display = vesafb_pan_display,
+       .fb_blank       = vesafb_blank,
        .fb_fillrect    = cfb_fillrect,
        .fb_copyarea    = cfb_copyarea,
        .fb_imageblit   = cfb_imageblit,
@@ -429,6 +463,10 @@ static int __init vesafb_probe(struct device *device)
        info->flags = FBINFO_FLAG_DEFAULT |
                (ypan) ? FBINFO_HWACCEL_YPAN : 0;
 
+       vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
+       printk("vesafb: Mode is %sVGA compatible\n",
+              (vga_compat) ? "" : "not ");
+
        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
                err = -ENOMEM;
                goto err;
index 0ea62d8bc703d1550f9d9a005d97cfb16c17ba76..ca92940f39438d9d7b4bffe0456815a2421b6b58 100644 (file)
@@ -342,16 +342,11 @@ static void vga_cleanup(struct vgastate *state)
        if (state->vidstate != NULL) {
                struct regstate *saved = (struct regstate *) state->vidstate;
 
-               if (saved->vga_font0) 
-                       vfree(saved->vga_font0);
-               if (saved->vga_font1) 
-                       vfree(saved->vga_font1);
-               if (saved->vga_text)
-                       vfree(saved->vga_text);
-               if (saved->vga_cmap)
-                       vfree(saved->vga_cmap);
-               if (saved->attr)
-                       vfree(saved->attr);
+               vfree(saved->vga_font0);
+               vfree(saved->vga_font1);
+               vfree(saved->vga_text);
+               vfree(saved->vga_cmap);
+               vfree(saved->attr);
                kfree(saved);
                state->vidstate = NULL;
        }
index b7c24b34d270db1129009b374d52710a012c0287..279e0e0363d6afb7e7326da42381d6c36c5e37f4 100644 (file)
 #include <linux/delay.h>
 #ifdef CONFIG_W1_F23_CRC
 #include <linux/crc16.h>
+
+#define CRC16_INIT             0
+#define CRC16_VALID            0xb001
+
 #endif
 
 #include "w1.h"
@@ -214,7 +218,7 @@ static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
 #ifdef CONFIG_W1_F23_CRC
        /* can only write full blocks in cached mode */
        if ((off & W1_PAGE_MASK) || (count & W1_PAGE_MASK)) {
-               dev_err(&sl->dev, "invalid offset/count off=%d cnt=%d\n",
+               dev_err(&sl->dev, "invalid offset/count off=%d cnt=%zd\n",
                        (int)off, count);
                return -EINVAL;
        }
diff --git a/fs/9p/9p.c b/fs/9p/9p.c
new file mode 100644 (file)
index 0000000..e847f50
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ *  linux/fs/9p/9p.c
+ *
+ *  This file contains functions 9P2000 functions
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "mux.h"
+
+/**
+ * v9fs_t_version - negotiate protocol parameters with sever
+ * @v9ses: 9P2000 session information
+ * @msize: requested max size packet
+ * @version: requested version.extension string
+ * @fcall: pointer to response fcall pointer
+ *
+ */
+
+int
+v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
+              char *version, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
+       msg.id = TVERSION;
+       msg.params.tversion.msize = msize;
+       msg.params.tversion.version = version;
+
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_attach - mount the server
+ * @v9ses: 9P2000 session information
+ * @uname: user name doing the attach
+ * @aname: remote name being attached to
+ * @fid: mount fid to attatch to root node
+ * @afid: authentication fid (in this case result key)
+ * @fcall: pointer to response fcall pointer
+ *
+ */
+
+int
+v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
+             u32 fid, u32 afid, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
+               aname, fid, afid);
+       msg.id = TATTACH;
+       msg.params.tattach.fid = fid;
+       msg.params.tattach.afid = afid;
+       msg.params.tattach.uname = uname;
+       msg.params.tattach.aname = aname;
+
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_clunk - release a fid (finish a transaction)
+ * @v9ses: 9P2000 session information
+ * @fid: fid to release
+ * @fcall: pointer to response fcall pointer
+ *
+ */
+
+int
+v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
+            struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "fid %d\n", fid);
+       msg.id = TCLUNK;
+       msg.params.tclunk.fid = fid;
+
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_v9fs_t_flush - flush a pending transaction
+ * @v9ses: 9P2000 session information
+ * @tag: tid to release
+ *
+ */
+
+int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "oldtag %d\n", tag);
+       msg.id = TFLUSH;
+       msg.params.tflush.oldtag = tag;
+       return v9fs_mux_rpc(v9ses, &msg, NULL);
+}
+
+/**
+ * v9fs_t_stat - read a file's meta-data
+ * @v9ses: 9P2000 session information
+ * @fid: fid pointing to file or directory to get info about
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "fid %d\n", fid);
+       if (fcall)
+               *fcall = NULL;
+
+       msg.id = TSTAT;
+       msg.params.tstat.fid = fid;
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_wstat - write a file's meta-data
+ * @v9ses: 9P2000 session information
+ * @fid: fid pointing to file or directory to write info about
+ * @stat: metadata
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
+            struct v9fs_stat *stat, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "fid %d length %d\n", fid, (int)stat->length);
+       msg.id = TWSTAT;
+       msg.params.twstat.fid = fid;
+       msg.params.twstat.stat = stat;
+
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_walk - walk a fid to a new file or directory
+ * @v9ses: 9P2000 session information
+ * @fid: fid to walk
+ * @newfid: new fid (for clone operations)
+ * @name: path to walk fid to
+ * @fcall: pointer to response fcall
+ *
+ */
+
+/* TODO: support multiple walk */
+
+int
+v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
+           char *name, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
+       msg.id = TWALK;
+       msg.params.twalk.fid = fid;
+       msg.params.twalk.newfid = newfid;
+
+       if (name) {
+               msg.params.twalk.nwname = 1;
+               msg.params.twalk.wnames = &name;
+       } else {
+               msg.params.twalk.nwname = 0;
+       }
+
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_open - open a file
+ *
+ * @v9ses - 9P2000 session information
+ * @fid - fid to open
+ * @mode - mode to open file (R, RW, etc)
+ * @fcall - pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
+           struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+       long errorno = -1;
+
+       dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
+       msg.id = TOPEN;
+       msg.params.topen.fid = fid;
+       msg.params.topen.mode = mode;
+
+       errorno = v9fs_mux_rpc(v9ses, &msg, fcall);
+
+       return errorno;
+}
+
+/**
+ * v9fs_t_remove - remove a file or directory
+ * @v9ses: 9P2000 session information
+ * @fid: fid to remove
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
+             struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "fid %d\n", fid);
+       msg.id = TREMOVE;
+       msg.params.tremove.fid = fid;
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_create - create a file or directory
+ * @v9ses: 9P2000 session information
+ * @fid: fid to create
+ * @name: name of the file or directory to create
+ * @perm: permissions to create with
+ * @mode: mode to open file (R, RW, etc)
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
+             u32 perm, u8 mode, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+
+       dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
+               fid, name, perm, mode);
+
+       msg.id = TCREATE;
+       msg.params.tcreate.fid = fid;
+       msg.params.tcreate.name = name;
+       msg.params.tcreate.perm = perm;
+       msg.params.tcreate.mode = mode;
+
+       return v9fs_mux_rpc(v9ses, &msg, fcall);
+}
+
+/**
+ * v9fs_t_read - read data
+ * @v9ses: 9P2000 session information
+ * @fid: fid to read from
+ * @offset: offset to start read at
+ * @count: how many bytes to read
+ * @fcall: pointer to response fcall (with data)
+ *
+ */
+
+int
+v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
+           u32 count, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+       struct v9fs_fcall *rc = NULL;
+       long errorno = -1;
+
+       dprintk(DEBUG_9P, "fid %d offset 0x%lx count 0x%x\n", fid,
+               (long unsigned int)offset, count);
+       msg.id = TREAD;
+       msg.params.tread.fid = fid;
+       msg.params.tread.offset = offset;
+       msg.params.tread.count = count;
+       errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
+
+       if (!errorno) {
+               errorno = rc->params.rread.count;
+               dump_data(rc->params.rread.data, rc->params.rread.count);
+       }
+
+       if (fcall)
+               *fcall = rc;
+       else
+               kfree(rc);
+
+       return errorno;
+}
+
+/**
+ * v9fs_t_write - write data
+ * @v9ses: 9P2000 session information
+ * @fid: fid to write to
+ * @offset: offset to start write at
+ * @count: how many bytes to write
+ * @fcall: pointer to response fcall
+ *
+ */
+
+int
+v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid,
+            u64 offset, u32 count, void *data, struct v9fs_fcall **fcall)
+{
+       struct v9fs_fcall msg;
+       struct v9fs_fcall *rc = NULL;
+       long errorno = -1;
+
+       dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid,
+               (unsigned long long)offset, count);
+       dump_data(data, count);
+
+       msg.id = TWRITE;
+       msg.params.twrite.fid = fid;
+       msg.params.twrite.offset = offset;
+       msg.params.twrite.count = count;
+       msg.params.twrite.data = data;
+
+       errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
+
+       if (!errorno)
+               errorno = rc->params.rwrite.count;
+
+       if (fcall)
+               *fcall = rc;
+       else
+               kfree(rc);
+
+       return errorno;
+}
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
new file mode 100644 (file)
index 0000000..f554242
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * linux/fs/9p/9p.h
+ *
+ * 9P protocol definitions.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+/* Message Types */
+enum {
+       TVERSION = 100,
+       RVERSION,
+       TAUTH = 102,
+       RAUTH,
+       TATTACH = 104,
+       RATTACH,
+       TERROR = 106,
+       RERROR,
+       TFLUSH = 108,
+       RFLUSH,
+       TWALK = 110,
+       RWALK,
+       TOPEN = 112,
+       ROPEN,
+       TCREATE = 114,
+       RCREATE,
+       TREAD = 116,
+       RREAD,
+       TWRITE = 118,
+       RWRITE,
+       TCLUNK = 120,
+       RCLUNK,
+       TREMOVE = 122,
+       RREMOVE,
+       TSTAT = 124,
+       RSTAT,
+       TWSTAT = 126,
+       RWSTAT,
+};
+
+/* modes */
+enum {
+       V9FS_OREAD = 0x00,
+       V9FS_OWRITE = 0x01,
+       V9FS_ORDWR = 0x02,
+       V9FS_OEXEC = 0x03,
+       V9FS_OEXCL = 0x04,
+       V9FS_OTRUNC = 0x10,
+       V9FS_OREXEC = 0x20,
+       V9FS_ORCLOSE = 0x40,
+       V9FS_OAPPEND = 0x80,
+};
+
+/* permissions */
+enum {
+       V9FS_DMDIR = 0x80000000,
+       V9FS_DMAPPEND = 0x40000000,
+       V9FS_DMEXCL = 0x20000000,
+       V9FS_DMMOUNT = 0x10000000,
+       V9FS_DMAUTH = 0x08000000,
+       V9FS_DMTMP = 0x04000000,
+       V9FS_DMSYMLINK = 0x02000000,
+       V9FS_DMLINK = 0x01000000,
+       /* 9P2000.u extensions */
+       V9FS_DMDEVICE = 0x00800000,
+       V9FS_DMNAMEDPIPE = 0x00200000,
+       V9FS_DMSOCKET = 0x00100000,
+       V9FS_DMSETUID = 0x00080000,
+       V9FS_DMSETGID = 0x00040000,
+};
+
+/* qid.types */
+enum {
+       V9FS_QTDIR = 0x80,
+       V9FS_QTAPPEND = 0x40,
+       V9FS_QTEXCL = 0x20,
+       V9FS_QTMOUNT = 0x10,
+       V9FS_QTAUTH = 0x08,
+       V9FS_QTTMP = 0x04,
+       V9FS_QTSYMLINK = 0x02,
+       V9FS_QTLINK = 0x01,
+       V9FS_QTFILE = 0x00,
+};
+
+/* ample room for Twrite/Rread header (iounit) */
+#define V9FS_IOHDRSZ   24
+
+/* qids are the unique ID for a file (like an inode */
+struct v9fs_qid {
+       u8 type;
+       u32 version;
+       u64 path;
+};
+
+/* Plan 9 file metadata (stat) structure */
+struct v9fs_stat {
+       u16 size;
+       u16 type;
+       u32 dev;
+       struct v9fs_qid qid;
+       u32 mode;
+       u32 atime;
+       u32 mtime;
+       u64 length;
+       char *name;
+       char *uid;
+       char *gid;
+       char *muid;
+       char *extension;        /* 9p2000.u extensions */
+       u32 n_uid;              /* 9p2000.u extensions */
+       u32 n_gid;              /* 9p2000.u extensions */
+       u32 n_muid;             /* 9p2000.u extensions */
+       char data[0];
+};
+
+/* Structures for Protocol Operations */
+
+struct Tversion {
+       u32 msize;
+       char *version;
+};
+
+struct Rversion {
+       u32 msize;
+       char *version;
+};
+
+struct Tauth {
+       u32 afid;
+       char *uname;
+       char *aname;
+};
+
+struct Rauth {
+       struct v9fs_qid qid;
+};
+
+struct Rerror {
+       char *error;
+       u32 errno;              /* 9p2000.u extension */
+};
+
+struct Tflush {
+       u32 oldtag;
+};
+
+struct Rflush {
+};
+
+struct Tattach {
+       u32 fid;
+       u32 afid;
+       char *uname;
+       char *aname;
+};
+
+struct Rattach {
+       struct v9fs_qid qid;
+};
+
+struct Twalk {
+       u32 fid;
+       u32 newfid;
+       u32 nwname;
+       char **wnames;
+};
+
+struct Rwalk {
+       u32 nwqid;
+       struct v9fs_qid *wqids;
+};
+
+struct Topen {
+       u32 fid;
+       u8 mode;
+};
+
+struct Ropen {
+       struct v9fs_qid qid;
+       u32 iounit;
+};
+
+struct Tcreate {
+       u32 fid;
+       char *name;
+       u32 perm;
+       u8 mode;
+};
+
+struct Rcreate {
+       struct v9fs_qid qid;
+       u32 iounit;
+};
+
+struct Tread {
+       u32 fid;
+       u64 offset;
+       u32 count;
+};
+
+struct Rread {
+       u32 count;
+       u8 *data;
+};
+
+struct Twrite {
+       u32 fid;
+       u64 offset;
+       u32 count;
+       u8 *data;
+};
+
+struct Rwrite {
+       u32 count;
+};
+
+struct Tclunk {
+       u32 fid;
+};
+
+struct Rclunk {
+};
+
+struct Tremove {
+       u32 fid;
+};
+
+struct Rremove {
+};
+
+struct Tstat {
+       u32 fid;
+};
+
+struct Rstat {
+       struct v9fs_stat *stat;
+};
+
+struct Twstat {
+       u32 fid;
+       struct v9fs_stat *stat;
+};
+
+struct Rwstat {
+};
+
+/*
+  * fcall is the primary packet structure
+  *
+  */
+
+struct v9fs_fcall {
+       u32 size;
+       u8 id;
+       u16 tag;
+
+       union {
+               struct Tversion tversion;
+               struct Rversion rversion;
+               struct Tauth tauth;
+               struct Rauth rauth;
+               struct Rerror rerror;
+               struct Tflush tflush;
+               struct Rflush rflush;
+               struct Tattach tattach;
+               struct Rattach rattach;
+               struct Twalk twalk;
+               struct Rwalk rwalk;
+               struct Topen topen;
+               struct Ropen ropen;
+               struct Tcreate tcreate;
+               struct Rcreate rcreate;
+               struct Tread tread;
+               struct Rread rread;
+               struct Twrite twrite;
+               struct Rwrite rwrite;
+               struct Tclunk tclunk;
+               struct Rclunk rclunk;
+               struct Tremove tremove;
+               struct Rremove rremove;
+               struct Tstat tstat;
+               struct Rstat rstat;
+               struct Twstat twstat;
+               struct Rwstat rwstat;
+       } params;
+};
+
+#define FCALL_ERROR(fcall) (fcall ? fcall->params.rerror.error : "")
+
+int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
+                  char *version, struct v9fs_fcall **rcall);
+
+int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
+                 u32 fid, u32 afid, struct v9fs_fcall **rcall);
+
+int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
+                struct v9fs_fcall **rcall);
+
+int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag);
+
+int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
+               struct v9fs_fcall **rcall);
+
+int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
+                struct v9fs_stat *stat, struct v9fs_fcall **rcall);
+
+int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
+               char *name, struct v9fs_fcall **rcall);
+
+int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
+               struct v9fs_fcall **rcall);
+
+int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
+                 struct v9fs_fcall **rcall);
+
+int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
+                 u32 perm, u8 mode, struct v9fs_fcall **rcall);
+
+int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
+               u64 offset, u32 count, struct v9fs_fcall **rcall);
+
+int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
+                u32 count, void *data, struct v9fs_fcall **rcall);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
new file mode 100644 (file)
index 0000000..e4e4ffe
--- /dev/null
@@ -0,0 +1,17 @@
+obj-$(CONFIG_9P_FS) := 9p2000.o
+
+9p2000-objs := \
+       vfs_super.o \
+       vfs_inode.o \
+       vfs_file.o \
+       vfs_dir.o \
+       vfs_dentry.o \
+       error.o \
+       mux.o \
+       trans_fd.o \
+       trans_sock.o \
+       9p.o \
+       conv.o \
+       v9fs.o \
+       fid.o
+
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
new file mode 100644 (file)
index 0000000..1554731
--- /dev/null
@@ -0,0 +1,693 @@
+/*
+ * linux/fs/9p/conv.c
+ *
+ * 9P protocol conversion functions
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "conv.h"
+
+/*
+ * Buffer to help with string parsing
+ */
+struct cbuf {
+       unsigned char *sp;
+       unsigned char *p;
+       unsigned char *ep;
+};
+
+static inline void buf_init(struct cbuf *buf, void *data, int datalen)
+{
+       buf->sp = buf->p = data;
+       buf->ep = data + datalen;
+}
+
+static inline int buf_check_overflow(struct cbuf *buf)
+{
+       return buf->p > buf->ep;
+}
+
+static inline void buf_check_size(struct cbuf *buf, int len)
+{
+       if (buf->p+len > buf->ep) {
+               if (buf->p < buf->ep) {
+                       eprintk(KERN_ERR, "buffer overflow\n");
+                       buf->p = buf->ep + 1;
+               }
+       }
+}
+
+static inline void *buf_alloc(struct cbuf *buf, int len)
+{
+       void *ret = NULL;
+
+       buf_check_size(buf, len);
+       ret = buf->p;
+       buf->p += len;
+
+       return ret;
+}
+
+static inline void buf_put_int8(struct cbuf *buf, u8 val)
+{
+       buf_check_size(buf, 1);
+
+       buf->p[0] = val;
+       buf->p++;
+}
+
+static inline void buf_put_int16(struct cbuf *buf, u16 val)
+{
+       buf_check_size(buf, 2);
+
+       *(__le16 *) buf->p = cpu_to_le16(val);
+       buf->p += 2;
+}
+
+static inline void buf_put_int32(struct cbuf *buf, u32 val)
+{
+       buf_check_size(buf, 4);
+
+       *(__le32 *)buf->p = cpu_to_le32(val);
+       buf->p += 4;
+}
+
+static inline void buf_put_int64(struct cbuf *buf, u64 val)
+{
+       buf_check_size(buf, 8);
+
+       *(__le64 *)buf->p = cpu_to_le64(val);
+       buf->p += 8;
+}
+
+static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
+{
+       buf_check_size(buf, slen + 2);
+
+       buf_put_int16(buf, slen);
+       memcpy(buf->p, s, slen);
+       buf->p += slen;
+}
+
+static inline void buf_put_string(struct cbuf *buf, const char *s)
+{
+       buf_put_stringn(buf, s, strlen(s));
+}
+
+static inline void buf_put_data(struct cbuf *buf, void *data, u32 datalen)
+{
+       buf_check_size(buf, datalen);
+
+       memcpy(buf->p, data, datalen);
+       buf->p += datalen;
+}
+
+static inline u8 buf_get_int8(struct cbuf *buf)
+{
+       u8 ret = 0;
+
+       buf_check_size(buf, 1);
+       ret = buf->p[0];
+
+       buf->p++;
+
+       return ret;
+}
+
+static inline u16 buf_get_int16(struct cbuf *buf)
+{
+       u16 ret = 0;
+
+       buf_check_size(buf, 2);
+       ret = le16_to_cpu(*(__le16 *)buf->p);
+
+       buf->p += 2;
+
+       return ret;
+}
+
+static inline u32 buf_get_int32(struct cbuf *buf)
+{
+       u32 ret = 0;
+
+       buf_check_size(buf, 4);
+       ret = le32_to_cpu(*(__le32 *)buf->p);
+
+       buf->p += 4;
+
+       return ret;
+}
+
+static inline u64 buf_get_int64(struct cbuf *buf)
+{
+       u64 ret = 0;
+
+       buf_check_size(buf, 8);
+       ret = le64_to_cpu(*(__le64 *)buf->p);
+
+       buf->p += 8;
+
+       return ret;
+}
+
+static inline int
+buf_get_string(struct cbuf *buf, char *data, unsigned int datalen)
+{
+
+       u16 len = buf_get_int16(buf);
+       buf_check_size(buf, len);
+       if (len + 1 > datalen)
+               return 0;
+
+       memcpy(data, buf->p, len);
+       data[len] = 0;
+       buf->p += len;
+
+       return len + 1;
+}
+
+static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
+{
+       char *ret = NULL;
+       int n = buf_get_string(buf, sbuf->p, sbuf->ep - sbuf->p);
+
+       if (n > 0) {
+               ret = sbuf->p;
+               sbuf->p += n;
+       }
+
+       return ret;
+}
+
+static inline int buf_get_data(struct cbuf *buf, void *data, int datalen)
+{
+       buf_check_size(buf, datalen);
+
+       memcpy(data, buf->p, datalen);
+       buf->p += datalen;
+
+       return datalen;
+}
+
+static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
+                                 int datalen)
+{
+       char *ret = NULL;
+       int n = 0;
+
+       buf_check_size(dbuf, datalen);
+
+       n = buf_get_data(buf, dbuf->p, datalen);
+
+       if (n > 0) {
+               ret = dbuf->p;
+               dbuf->p += n;
+       }
+
+       return ret;
+}
+
+/**
+ * v9fs_size_stat - calculate the size of a variable length stat struct
+ * @v9ses: session information
+ * @stat: metadata (stat) structure
+ *
+ */
+
+static int v9fs_size_stat(struct v9fs_session_info *v9ses,
+                         struct v9fs_stat *stat)
+{
+       int size = 0;
+
+       if (stat == NULL) {
+               eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
+               return 0;
+       }
+
+       size =                  /* 2 + *//* size[2] */
+           2 +                 /* type[2] */
+           4 +                 /* dev[4] */
+           1 +                 /* qid.type[1] */
+           4 +                 /* qid.vers[4] */
+           8 +                 /* qid.path[8] */
+           4 +                 /* mode[4] */
+           4 +                 /* atime[4] */
+           4 +                 /* mtime[4] */
+           8 +                 /* length[8] */
+           8;                  /* minimum sum of string lengths */
+
+       if (stat->name)
+               size += strlen(stat->name);
+       if (stat->uid)
+               size += strlen(stat->uid);
+       if (stat->gid)
+               size += strlen(stat->gid);
+       if (stat->muid)
+               size += strlen(stat->muid);
+
+       if (v9ses->extended) {
+               size += 4 +     /* n_uid[4] */
+                   4 +         /* n_gid[4] */
+                   4 +         /* n_muid[4] */
+                   2;          /* string length of extension[4] */
+               if (stat->extension)
+                       size += strlen(stat->extension);
+       }
+
+       return size;
+}
+
+/**
+ * serialize_stat - safely format a stat structure for transmission
+ * @v9ses: session info
+ * @stat: metadata (stat) structure
+ * @bufp: buffer to serialize structure into
+ *
+ */
+
+static int
+serialize_stat(struct v9fs_session_info *v9ses, struct v9fs_stat *stat,
+              struct cbuf *bufp)
+{
+       buf_put_int16(bufp, stat->size);
+       buf_put_int16(bufp, stat->type);
+       buf_put_int32(bufp, stat->dev);
+       buf_put_int8(bufp, stat->qid.type);
+       buf_put_int32(bufp, stat->qid.version);
+       buf_put_int64(bufp, stat->qid.path);
+       buf_put_int32(bufp, stat->mode);
+       buf_put_int32(bufp, stat->atime);
+       buf_put_int32(bufp, stat->mtime);
+       buf_put_int64(bufp, stat->length);
+
+       buf_put_string(bufp, stat->name);
+       buf_put_string(bufp, stat->uid);
+       buf_put_string(bufp, stat->gid);
+       buf_put_string(bufp, stat->muid);
+
+       if (v9ses->extended) {
+               buf_put_string(bufp, stat->extension);
+               buf_put_int32(bufp, stat->n_uid);
+               buf_put_int32(bufp, stat->n_gid);
+               buf_put_int32(bufp, stat->n_muid);
+       }
+
+       if (buf_check_overflow(bufp))
+               return 0;
+
+       return stat->size;
+}
+
+/**
+ * deserialize_stat - safely decode a recieved metadata (stat) structure
+ * @v9ses: session info
+ * @bufp: buffer to deserialize
+ * @stat: metadata (stat) structure
+ * @dbufp: buffer to deserialize variable strings into
+ *
+ */
+
+static inline int
+deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *bufp,
+                struct v9fs_stat *stat, struct cbuf *dbufp)
+{
+
+       stat->size = buf_get_int16(bufp);
+       stat->type = buf_get_int16(bufp);
+       stat->dev = buf_get_int32(bufp);
+       stat->qid.type = buf_get_int8(bufp);
+       stat->qid.version = buf_get_int32(bufp);
+       stat->qid.path = buf_get_int64(bufp);
+       stat->mode = buf_get_int32(bufp);
+       stat->atime = buf_get_int32(bufp);
+       stat->mtime = buf_get_int32(bufp);
+       stat->length = buf_get_int64(bufp);
+       stat->name = buf_get_stringb(bufp, dbufp);
+       stat->uid = buf_get_stringb(bufp, dbufp);
+       stat->gid = buf_get_stringb(bufp, dbufp);
+       stat->muid = buf_get_stringb(bufp, dbufp);
+
+       if (v9ses->extended) {
+               stat->extension = buf_get_stringb(bufp, dbufp);
+               stat->n_uid = buf_get_int32(bufp);
+               stat->n_gid = buf_get_int32(bufp);
+               stat->n_muid = buf_get_int32(bufp);
+       }
+
+       if (buf_check_overflow(bufp) || buf_check_overflow(dbufp))
+               return 0;
+
+       return stat->size + 2;
+}
+
+/**
+ * deserialize_statb - wrapper for decoding a received metadata structure
+ * @v9ses: session info
+ * @bufp: buffer to deserialize
+ * @dbufp: buffer to deserialize variable strings into
+ *
+ */
+
+static inline struct v9fs_stat *deserialize_statb(struct v9fs_session_info
+                                                 *v9ses, struct cbuf *bufp,
+                                                 struct cbuf *dbufp)
+{
+       struct v9fs_stat *ret = buf_alloc(dbufp, sizeof(struct v9fs_stat));
+
+       if (ret) {
+               int n = deserialize_stat(v9ses, bufp, ret, dbufp);
+               if (n <= 0)
+                       return NULL;
+       }
+
+       return ret;
+}
+
+/**
+ * v9fs_deserialize_stat - decode a received metadata structure
+ * @v9ses: session info
+ * @buf: buffer to deserialize
+ * @buflen: length of received buffer
+ * @stat: metadata structure to decode into
+ * @statlen: length of destination metadata structure
+ *
+ */
+
+int
+v9fs_deserialize_stat(struct v9fs_session_info *v9ses, void *buf,
+                     u32 buflen, struct v9fs_stat *stat, u32 statlen)
+{
+       struct cbuf buffer;
+       struct cbuf *bufp = &buffer;
+       struct cbuf dbuffer;
+       struct cbuf *dbufp = &dbuffer;
+
+       buf_init(bufp, buf, buflen);
+       buf_init(dbufp, (char *)stat + sizeof(struct v9fs_stat),
+                statlen - sizeof(struct v9fs_stat));
+
+       return deserialize_stat(v9ses, bufp, stat, dbufp);
+}
+
+static inline int
+v9fs_size_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall)
+{
+       int size = 4 + 1 + 2;   /* size[4] msg[1] tag[2] */
+       int i = 0;
+
+       switch (fcall->id) {
+       default:
+               eprintk(KERN_ERR, "bad msg type %d\n", fcall->id);
+               return 0;
+       case TVERSION:          /* msize[4] version[s] */
+               size += 4 + 2 + strlen(fcall->params.tversion.version);
+               break;
+       case TAUTH:             /* afid[4] uname[s] aname[s] */
+               size += 4 + 2 + strlen(fcall->params.tauth.uname) +
+                   2 + strlen(fcall->params.tauth.aname);
+               break;
+       case TFLUSH:            /* oldtag[2] */
+               size += 2;
+               break;
+       case TATTACH:           /* fid[4] afid[4] uname[s] aname[s] */
+               size += 4 + 4 + 2 + strlen(fcall->params.tattach.uname) +
+                   2 + strlen(fcall->params.tattach.aname);
+               break;
+       case TWALK:             /* fid[4] newfid[4] nwname[2] nwname*(wname[s]) */
+               size += 4 + 4 + 2;
+               /* now compute total for the array of names */
+               for (i = 0; i < fcall->params.twalk.nwname; i++)
+                       size += 2 + strlen(fcall->params.twalk.wnames[i]);
+               break;
+       case TOPEN:             /* fid[4] mode[1] */
+               size += 4 + 1;
+               break;
+       case TCREATE:           /* fid[4] name[s] perm[4] mode[1] */
+               size += 4 + 2 + strlen(fcall->params.tcreate.name) + 4 + 1;
+               break;
+       case TREAD:             /* fid[4] offset[8] count[4] */
+               size += 4 + 8 + 4;
+               break;
+       case TWRITE:            /* fid[4] offset[8] count[4] data[count] */
+               size += 4 + 8 + 4 + fcall->params.twrite.count;
+               break;
+       case TCLUNK:            /* fid[4] */
+               size += 4;
+               break;
+       case TREMOVE:           /* fid[4] */
+               size += 4;
+               break;
+       case TSTAT:             /* fid[4] */
+               size += 4;
+               break;
+       case TWSTAT:            /* fid[4] stat[n] */
+               fcall->params.twstat.stat->size =
+                   v9fs_size_stat(v9ses, fcall->params.twstat.stat);
+               size += 4 + 2 + 2 + fcall->params.twstat.stat->size;
+       }
+       return size;
+}
+
+/*
+ * v9fs_serialize_fcall - marshall fcall struct into a packet
+ * @v9ses: session information
+ * @fcall: structure to convert
+ * @data: buffer to serialize fcall into
+ * @datalen: length of buffer to serialize fcall into
+ *
+ */
+
+int
+v9fs_serialize_fcall(struct v9fs_session_info *v9ses, struct v9fs_fcall *fcall,
+                    void *data, u32 datalen)
+{
+       int i = 0;
+       struct v9fs_stat *stat = NULL;
+       struct cbuf buffer;
+       struct cbuf *bufp = &buffer;
+
+       buf_init(bufp, data, datalen);
+
+       if (!fcall) {
+               eprintk(KERN_ERR, "no fcall\n");
+               return -EINVAL;
+       }
+
+       fcall->size = v9fs_size_fcall(v9ses, fcall);
+
+       buf_put_int32(bufp, fcall->size);
+       buf_put_int8(bufp, fcall->id);
+       buf_put_int16(bufp, fcall->tag);
+
+       dprintk(DEBUG_CONV, "size %d id %d tag %d\n", fcall->size, fcall->id,
+               fcall->tag);
+
+       /* now encode it */
+       switch (fcall->id) {
+       default:
+               eprintk(KERN_ERR, "bad msg type: %d\n", fcall->id);
+               return -EPROTO;
+       case TVERSION:
+               buf_put_int32(bufp, fcall->params.tversion.msize);
+               buf_put_string(bufp, fcall->params.tversion.version);
+               break;
+       case TAUTH:
+               buf_put_int32(bufp, fcall->params.tauth.afid);
+               buf_put_string(bufp, fcall->params.tauth.uname);
+               buf_put_string(bufp, fcall->params.tauth.aname);
+               break;
+       case TFLUSH:
+               buf_put_int16(bufp, fcall->params.tflush.oldtag);
+               break;
+       case TATTACH:
+               buf_put_int32(bufp, fcall->params.tattach.fid);
+               buf_put_int32(bufp, fcall->params.tattach.afid);
+               buf_put_string(bufp, fcall->params.tattach.uname);
+               buf_put_string(bufp, fcall->params.tattach.aname);
+               break;
+       case TWALK:
+               buf_put_int32(bufp, fcall->params.twalk.fid);
+               buf_put_int32(bufp, fcall->params.twalk.newfid);
+               buf_put_int16(bufp, fcall->params.twalk.nwname);
+               for (i = 0; i < fcall->params.twalk.nwname; i++)
+                       buf_put_string(bufp, fcall->params.twalk.wnames[i]);
+               break;
+       case TOPEN:
+               buf_put_int32(bufp, fcall->params.topen.fid);
+               buf_put_int8(bufp, fcall->params.topen.mode);
+               break;
+       case TCREATE:
+               buf_put_int32(bufp, fcall->params.tcreate.fid);
+               buf_put_string(bufp, fcall->params.tcreate.name);
+               buf_put_int32(bufp, fcall->params.tcreate.perm);
+               buf_put_int8(bufp, fcall->params.tcreate.mode);
+               break;
+       case TREAD:
+               buf_put_int32(bufp, fcall->params.tread.fid);
+               buf_put_int64(bufp, fcall->params.tread.offset);
+               buf_put_int32(bufp, fcall->params.tread.count);
+               break;
+       case TWRITE:
+               buf_put_int32(bufp, fcall->params.twrite.fid);
+               buf_put_int64(bufp, fcall->params.twrite.offset);
+               buf_put_int32(bufp, fcall->params.twrite.count);
+               buf_put_data(bufp, fcall->params.twrite.data,
+                            fcall->params.twrite.count);
+               break;
+       case TCLUNK:
+               buf_put_int32(bufp, fcall->params.tclunk.fid);
+               break;
+       case TREMOVE:
+               buf_put_int32(bufp, fcall->params.tremove.fid);
+               break;
+       case TSTAT:
+               buf_put_int32(bufp, fcall->params.tstat.fid);
+               break;
+       case TWSTAT:
+               buf_put_int32(bufp, fcall->params.twstat.fid);
+               stat = fcall->params.twstat.stat;
+
+               buf_put_int16(bufp, stat->size + 2);
+               serialize_stat(v9ses, stat, bufp);
+               break;
+       }
+
+       if (buf_check_overflow(bufp))
+               return -EIO;
+
+       return fcall->size;
+}
+
+/**
+ * deserialize_fcall - unmarshal a response
+ * @v9ses: session information
+ * @msgsize: size of rcall message
+ * @buf: recieved buffer
+ * @buflen: length of received buffer
+ * @rcall: fcall structure to populate
+ * @rcalllen: length of fcall structure to populate
+ *
+ */
+
+int
+v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize,
+                      void *buf, u32 buflen, struct v9fs_fcall *rcall,
+                      int rcalllen)
+{
+
+       struct cbuf buffer;
+       struct cbuf *bufp = &buffer;
+       struct cbuf dbuffer;
+       struct cbuf *dbufp = &dbuffer;
+       int i = 0;
+
+       buf_init(bufp, buf, buflen);
+       buf_init(dbufp, (char *)rcall + sizeof(struct v9fs_fcall),
+                rcalllen - sizeof(struct v9fs_fcall));
+
+       rcall->size = msgsize;
+       rcall->id = buf_get_int8(bufp);
+       rcall->tag = buf_get_int16(bufp);
+
+       dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id,
+               rcall->tag);
+       switch (rcall->id) {
+       default:
+               eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id);
+               return -EPROTO;
+       case RVERSION:
+               rcall->params.rversion.msize = buf_get_int32(bufp);
+               rcall->params.rversion.version = buf_get_stringb(bufp, dbufp);
+               break;
+       case RFLUSH:
+               break;
+       case RATTACH:
+               rcall->params.rattach.qid.type = buf_get_int8(bufp);
+               rcall->params.rattach.qid.version = buf_get_int32(bufp);
+               rcall->params.rattach.qid.path = buf_get_int64(bufp);
+               break;
+       case RWALK:
+               rcall->params.rwalk.nwqid = buf_get_int16(bufp);
+               rcall->params.rwalk.wqids = buf_alloc(bufp,
+                     rcall->params.rwalk.nwqid * sizeof(struct v9fs_qid));
+               if (rcall->params.rwalk.wqids)
+                       for (i = 0; i < rcall->params.rwalk.nwqid; i++) {
+                               rcall->params.rwalk.wqids[i].type =
+                                   buf_get_int8(bufp);
+                               rcall->params.rwalk.wqids[i].version =
+                                   buf_get_int16(bufp);
+                               rcall->params.rwalk.wqids[i].path =
+                                   buf_get_int64(bufp);
+                       }
+               break;
+       case ROPEN:
+               rcall->params.ropen.qid.type = buf_get_int8(bufp);
+               rcall->params.ropen.qid.version = buf_get_int32(bufp);
+               rcall->params.ropen.qid.path = buf_get_int64(bufp);
+               rcall->params.ropen.iounit = buf_get_int32(bufp);
+               break;
+       case RCREATE:
+               rcall->params.rcreate.qid.type = buf_get_int8(bufp);
+               rcall->params.rcreate.qid.version = buf_get_int32(bufp);
+               rcall->params.rcreate.qid.path = buf_get_int64(bufp);
+               rcall->params.rcreate.iounit = buf_get_int32(bufp);
+               break;
+       case RREAD:
+               rcall->params.rread.count = buf_get_int32(bufp);
+               rcall->params.rread.data = buf_get_datab(bufp, dbufp,
+                       rcall->params.rread.count);
+               break;
+       case RWRITE:
+               rcall->params.rwrite.count = buf_get_int32(bufp);
+               break;
+       case RCLUNK:
+               break;
+       case RREMOVE:
+               break;
+       case RSTAT:
+               buf_get_int16(bufp);
+               rcall->params.rstat.stat =
+                   deserialize_statb(v9ses, bufp, dbufp);
+               break;
+       case RWSTAT:
+               break;
+       case RERROR:
+               rcall->params.rerror.error = buf_get_stringb(bufp, dbufp);
+               if (v9ses->extended)
+                       rcall->params.rerror.errno = buf_get_int16(bufp);
+               break;
+       }
+
+       if (buf_check_overflow(bufp) || buf_check_overflow(dbufp))
+               return -EIO;
+
+       return rcall->size;
+}
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
new file mode 100644 (file)
index 0000000..ee84961
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * linux/fs/9p/conv.h
+ *
+ * 9P protocol conversion definitions
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+int v9fs_deserialize_stat(struct v9fs_session_info *, void *buf,
+                         u32 buflen, struct v9fs_stat *stat, u32 statlen);
+int v9fs_serialize_fcall(struct v9fs_session_info *, struct v9fs_fcall *tcall,
+                        void *buf, u32 buflen);
+int v9fs_deserialize_fcall(struct v9fs_session_info *, u32 msglen,
+                          void *buf, u32 buflen, struct v9fs_fcall *rcall,
+                          int rcalllen);
+
+/* this one is actually in error.c right now */
+int v9fs_errstr2errno(char *errstr);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
new file mode 100644 (file)
index 0000000..4445f06
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  linux/fs/9p/debug.h - V9FS Debug Definitions
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#define DEBUG_ERROR            (1<<0)
+#define DEBUG_CURRENT          (1<<1)
+#define DEBUG_9P               (1<<2)
+#define DEBUG_VFS              (1<<3)
+#define DEBUG_CONV             (1<<4)
+#define DEBUG_MUX              (1<<5)
+#define DEBUG_TRANS            (1<<6)
+#define DEBUG_SLABS            (1<<7)
+
+#define DEBUG_DUMP_PKT         0
+
+extern int v9fs_debug_level;
+
+#define dprintk(level, format, arg...) \
+do {  \
+       if((v9fs_debug_level & level)==level) \
+               printk(KERN_NOTICE "-- %s (%d): " \
+               format , __FUNCTION__, current->pid , ## arg); \
+} while(0)
+
+#define eprintk(level, format, arg...) \
+do { \
+       printk(level "v9fs: %s (%d): " \
+               format , __FUNCTION__, current->pid , ## arg); \
+} while(0)
+
+#if DEBUG_DUMP_PKT
+static inline void dump_data(const unsigned char *data, unsigned int datalen)
+{
+       int i, j;
+       int len = datalen;
+
+       printk(KERN_DEBUG "data ");
+       for (i = 0; i < len; i += 4) {
+               for (j = 0; (j < 4) && (i + j < len); j++)
+                       printk(KERN_DEBUG "%02x", data[i + j]);
+               printk(KERN_DEBUG " ");
+       }
+       printk(KERN_DEBUG "\n");
+}
+#else                          /* DEBUG_DUMP_PKT */
+static inline void dump_data(const unsigned char *data, unsigned int datalen)
+{
+
+}
+#endif                         /* DEBUG_DUMP_PKT */
diff --git a/fs/9p/error.c b/fs/9p/error.c
new file mode 100644 (file)
index 0000000..fee5d19
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * linux/fs/9p/error.c
+ *
+ * Error string handling
+ *
+ * Plan 9 uses error strings, Unix uses error numbers.  These functions
+ * try to help manage that and provide for dynamically adding error
+ * mappings.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/list.h>
+#include <linux/jhash.h>
+
+#include "debug.h"
+#include "error.h"
+
+/**
+ * v9fs_error_init - preload
+ * @errstr: error string
+ *
+ */
+
+int v9fs_error_init(void)
+{
+       struct errormap *c;
+       int bucket;
+
+       /* initialize hash table */
+       for (bucket = 0; bucket < ERRHASHSZ; bucket++)
+               INIT_HLIST_HEAD(&hash_errmap[bucket]);
+
+       /* load initial error map into hash table */
+       for (c = errmap; c->name != NULL; c++) {
+               bucket = jhash(c->name, strlen(c->name), 0) % ERRHASHSZ;
+               INIT_HLIST_NODE(&c->list);
+               hlist_add_head(&c->list, &hash_errmap[bucket]);
+       }
+
+       return 1;
+}
+
+/**
+ * errstr2errno - convert error string to error number
+ * @errstr: error string
+ *
+ */
+
+int v9fs_errstr2errno(char *errstr)
+{
+       int errno = 0;
+       struct hlist_node *p = NULL;
+       struct errormap *c = NULL;
+       int bucket = jhash(errstr, strlen(errstr), 0) % ERRHASHSZ;
+
+       hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
+               if (!strcmp(c->name, errstr)) {
+                       errno = c->val;
+                       break;
+               }
+       }
+
+       if (errno == 0) {
+               /* TODO: if error isn't found, add it dynamically */
+               printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
+                      errstr);
+               errno = 1;
+       }
+
+       return -errno;
+}
diff --git a/fs/9p/error.h b/fs/9p/error.h
new file mode 100644 (file)
index 0000000..78f89ac
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * linux/fs/9p/error.h
+ *
+ * Huge Nasty Error Table
+ *
+ * Plan 9 uses error strings, Unix uses error numbers.  This table tries to
+ * match UNIX strings and Plan 9 strings to unix error numbers.  It is used
+ * to preload the dynamic error table which can also track user-specific error
+ * strings.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/errno.h>
+#include <asm/errno.h>
+
+struct errormap {
+       char *name;
+       int val;
+
+       struct hlist_node list;
+};
+
+#define ERRHASHSZ              32
+static struct hlist_head hash_errmap[ERRHASHSZ];
+
+/* FixMe - reduce to a reasonable size */
+static struct errormap errmap[] = {
+       {"Operation not permitted", EPERM},
+       {"wstat prohibited", EPERM},
+       {"No such file or directory", ENOENT},
+       {"directory entry not found", ENOENT},
+       {"file not found", ENOENT},
+       {"Interrupted system call", EINTR},
+       {"Input/output error", EIO},
+       {"No such device or address", ENXIO},
+       {"Argument list too long", E2BIG},
+       {"Bad file descriptor", EBADF},
+       {"Resource temporarily unavailable", EAGAIN},
+       {"Cannot allocate memory", ENOMEM},
+       {"Permission denied", EACCES},
+       {"Bad address", EFAULT},
+       {"Block device required", ENOTBLK},
+       {"Device or resource busy", EBUSY},
+       {"File exists", EEXIST},
+       {"Invalid cross-device link", EXDEV},
+       {"No such device", ENODEV},
+       {"Not a directory", ENOTDIR},
+       {"Is a directory", EISDIR},
+       {"Invalid argument", EINVAL},
+       {"Too many open files in system", ENFILE},
+       {"Too many open files", EMFILE},
+       {"Text file busy", ETXTBSY},
+       {"File too large", EFBIG},
+       {"No space left on device", ENOSPC},
+       {"Illegal seek", ESPIPE},
+       {"Read-only file system", EROFS},
+       {"Too many links", EMLINK},
+       {"Broken pipe", EPIPE},
+       {"Numerical argument out of domain", EDOM},
+       {"Numerical result out of range", ERANGE},
+       {"Resource deadlock avoided", EDEADLK},
+       {"File name too long", ENAMETOOLONG},
+       {"No locks available", ENOLCK},
+       {"Function not implemented", ENOSYS},
+       {"Directory not empty", ENOTEMPTY},
+       {"Too many levels of symbolic links", ELOOP},
+       {"No message of desired type", ENOMSG},
+       {"Identifier removed", EIDRM},
+       {"No data available", ENODATA},
+       {"Machine is not on the network", ENONET},
+       {"Package not installed", ENOPKG},
+       {"Object is remote", EREMOTE},
+       {"Link has been severed", ENOLINK},
+       {"Communication error on send", ECOMM},
+       {"Protocol error", EPROTO},
+       {"Bad message", EBADMSG},
+       {"File descriptor in bad state", EBADFD},
+       {"Streams pipe error", ESTRPIPE},
+       {"Too many users", EUSERS},
+       {"Socket operation on non-socket", ENOTSOCK},
+       {"Message too long", EMSGSIZE},
+       {"Protocol not available", ENOPROTOOPT},
+       {"Protocol not supported", EPROTONOSUPPORT},
+       {"Socket type not supported", ESOCKTNOSUPPORT},
+       {"Operation not supported", EOPNOTSUPP},
+       {"Protocol family not supported", EPFNOSUPPORT},
+       {"Network is down", ENETDOWN},
+       {"Network is unreachable", ENETUNREACH},
+       {"Network dropped connection on reset", ENETRESET},
+       {"Software caused connection abort", ECONNABORTED},
+       {"Connection reset by peer", ECONNRESET},
+       {"No buffer space available", ENOBUFS},
+       {"Transport endpoint is already connected", EISCONN},
+       {"Transport endpoint is not connected", ENOTCONN},
+       {"Cannot send after transport endpoint shutdown", ESHUTDOWN},
+       {"Connection timed out", ETIMEDOUT},
+       {"Connection refused", ECONNREFUSED},
+       {"Host is down", EHOSTDOWN},
+       {"No route to host", EHOSTUNREACH},
+       {"Operation already in progress", EALREADY},
+       {"Operation now in progress", EINPROGRESS},
+       {"Is a named type file", EISNAM},
+       {"Remote I/O error", EREMOTEIO},
+       {"Disk quota exceeded", EDQUOT},
+/* errors from fossil, vacfs, and u9fs */
+       {"fid unknown or out of range", EBADF},
+       {"permission denied", EACCES},
+       {"file does not exist", ENOENT},
+       {"authentication failed", ECONNREFUSED},
+       {"bad offset in directory read", ESPIPE},
+       {"bad use of fid", EBADF},
+       {"wstat can't convert between files and directories", EPERM},
+       {"directory is not empty", ENOTEMPTY},
+       {"file exists", EEXIST},
+       {"file already exists", EEXIST},
+       {"file or directory already exists", EEXIST},
+       {"fid already in use", EBADF},
+       {"file in use", ETXTBSY},
+       {"i/o error", EIO},
+       {"file already open for I/O", ETXTBSY},
+       {"illegal mode", EINVAL},
+       {"illegal name", ENAMETOOLONG},
+       {"not a directory", ENOTDIR},
+       {"not a member of proposed group", EPERM},
+       {"not owner", EACCES},
+       {"only owner can change group in wstat", EACCES},
+       {"read only file system", EROFS},
+       {"no access to special file", EPERM},
+       {"i/o count too large", EIO},
+       {"unknown group", EINVAL},
+       {"unknown user", EINVAL},
+       {"bogus wstat buffer", EPROTO},
+       {"exclusive use file already open", EAGAIN},
+       {"corrupted directory entry", EIO},
+       {"corrupted file entry", EIO},
+       {"corrupted block label", EIO},
+       {"corrupted meta data", EIO},
+       {"illegal offset", EINVAL},
+       {"illegal path element", ENOENT},
+       {"root of file system is corrupted", EIO},
+       {"corrupted super block", EIO},
+       {"protocol botch", EPROTO},
+       {"file system is full", ENOSPC},
+       {"file is in use", EAGAIN},
+       {"directory entry is not allocated", ENOENT},
+       {"file is read only", EROFS},
+       {"file has been removed", EIDRM},
+       {"only support truncation to zero length", EPERM},
+       {"cannot remove root", EPERM},
+       {"file too big", EFBIG},
+       {"venti i/o error", EIO},
+       /* these are not errors */
+       {"u9fs rhostsauth: no authentication required", 0},
+       {"u9fs authnone: no authentication required", 0},
+       {NULL, -1}
+};
+
+extern int v9fs_error_init(void);
+extern int v9fs_errstr2errno(char *errstr);
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
new file mode 100644 (file)
index 0000000..821c9c4
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * V9FS FID Management
+ *
+ *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "transport.h"
+#include "mux.h"
+#include "conv.h"
+#include "fid.h"
+
+/**
+ * v9fs_fid_insert - add a fid to a dentry
+ * @fid: fid to add
+ * @dentry: dentry that it is being added to
+ *
+ */
+
+static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
+{
+       struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
+       dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
+               dentry->d_iname, dentry);
+       if (dentry->d_fsdata == NULL) {
+               dentry->d_fsdata =
+                   kmalloc(sizeof(struct list_head), GFP_KERNEL);
+               if (dentry->d_fsdata == NULL) {
+                       dprintk(DEBUG_ERROR, "Out of memory\n");
+                       return -ENOMEM;
+               }
+               fid_list = (struct list_head *)dentry->d_fsdata;
+               INIT_LIST_HEAD(fid_list);       /* Initialize list head */
+       }
+
+       fid->uid = current->uid;
+       fid->pid = current->pid;
+       list_add(&fid->list, fid_list);
+       return 0;
+}
+
+/**
+ * v9fs_fid_create - allocate a FID structure
+ * @dentry - dentry to link newly created fid to
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_create(struct dentry *dentry)
+{
+       struct v9fs_fid *new;
+
+       new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+       if (new == NULL) {
+               dprintk(DEBUG_ERROR, "Out of Memory\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       new->fid = -1;
+       new->fidopen = 0;
+       new->fidcreate = 0;
+       new->fidclunked = 0;
+       new->iounit = 0;
+
+       if (v9fs_fid_insert(new, dentry) == 0)
+               return new;
+       else {
+               dprintk(DEBUG_ERROR, "Problems inserting to dentry\n");
+               kfree(new);
+               return NULL;
+       }
+}
+
+/**
+ * v9fs_fid_destroy - deallocate a FID structure
+ * @fid: fid to destroy
+ *
+ */
+
+void v9fs_fid_destroy(struct v9fs_fid *fid)
+{
+       list_del(&fid->list);
+       kfree(fid);
+}
+
+/**
+ * v9fs_fid_lookup - retrieve the right fid from a  particular dentry
+ * @dentry: dentry to look for fid in
+ * @type: intent of lookup (operation or traversal)
+ *
+ * search list of fids associated with a dentry for a fid with a matching
+ * thread id or uid.  If that fails, look up the dentry's parents to see if you
+ * can find a matching fid.
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type)
+{
+       struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
+       struct v9fs_fid *current_fid = NULL;
+       struct v9fs_fid *temp = NULL;
+       struct v9fs_fid *return_fid = NULL;
+       int found_parent = 0;
+       int found_user = 0;
+
+       dprintk(DEBUG_9P, " dentry: %s (%p) type %d\n", dentry->d_iname, dentry,
+               type);
+
+       if (fid_list && !list_empty(fid_list)) {
+               list_for_each_entry_safe(current_fid, temp, fid_list, list) {
+                       if (current_fid->uid == current->uid) {
+                               if (return_fid == NULL) {
+                                       if ((type == FID_OP)
+                                           || (!current_fid->fidopen)) {
+                                               return_fid = current_fid;
+                                               found_user = 1;
+                                       }
+                               }
+                       }
+                       if (current_fid->pid == current->real_parent->pid) {
+                               if ((return_fid == NULL) || (found_parent)
+                                   || (found_user)) {
+                                       if ((type == FID_OP)
+                                           || (!current_fid->fidopen)) {
+                                               return_fid = current_fid;
+                                               found_parent = 1;
+                                               found_user = 0;
+                                       }
+                               }
+                       }
+                       if (current_fid->pid == current->pid) {
+                               if ((type == FID_OP) ||
+                                   (!current_fid->fidopen)) {
+                                       return_fid = current_fid;
+                                       found_parent = 0;
+                                       found_user = 0;
+                               }
+                       }
+               }
+       }
+
+       /* we are at the root but didn't match */
+       if ((!return_fid) && (dentry->d_parent == dentry)) {
+               /* TODO: clone attach with new uid */
+               return_fid = current_fid;
+       }
+
+       if (!return_fid) {
+               struct dentry *par = current->fs->pwd->d_parent;
+               int count = 1;
+               while (par != NULL) {
+                       if (par == dentry)
+                               break;
+                       count++;
+                       if (par == par->d_parent) {
+                               dprintk(DEBUG_ERROR,
+                                       "got to root without finding dentry\n");
+                               break;
+                       }
+                       par = par->d_parent;
+               }
+
+/* XXX - there may be some duplication we can get rid of */
+               if (par == dentry) {
+                       /* we need to fid_lookup the starting point */
+                       int fidnum = -1;
+                       int oldfid = -1;
+                       int result = -1;
+                       struct v9fs_session_info *v9ses =
+                           v9fs_inode2v9ses(current->fs->pwd->d_inode);
+
+                       current_fid =
+                           v9fs_fid_lookup(current->fs->pwd, FID_WALK);
+                       if (current_fid == NULL) {
+                               dprintk(DEBUG_ERROR,
+                                       "process cwd doesn't have a fid\n");
+                               return return_fid;
+                       }
+                       oldfid = current_fid->fid;
+                       par = current->fs->pwd;
+                       /* TODO: take advantage of multiwalk */
+
+                       fidnum = v9fs_get_idpool(&v9ses->fidpool);
+                       if (fidnum < 0) {
+                               dprintk(DEBUG_ERROR,
+                                       "could not get a new fid num\n");
+                               return return_fid;
+                       }
+
+                       while (par != dentry) {
+                               result =
+                                   v9fs_t_walk(v9ses, oldfid, fidnum, "..",
+                                               NULL);
+                               if (result < 0) {
+                                       dprintk(DEBUG_ERROR,
+                                               "problem walking to parent\n");
+
+                                       break;
+                               }
+                               oldfid = fidnum;
+                               if (par == par->d_parent) {
+                                       dprintk(DEBUG_ERROR,
+                                               "can't find dentry\n");
+                                       break;
+                               }
+                               par = par->d_parent;
+                       }
+                       if (par == dentry) {
+                               return_fid = v9fs_fid_create(dentry);
+                               return_fid->fid = fidnum;
+                       }
+               }
+       }
+
+       return return_fid;
+}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
new file mode 100644 (file)
index 0000000..7db478c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * V9FS FID Management
+ *
+ *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/list.h>
+
+#define FID_OP   0
+#define FID_WALK 1
+
+struct v9fs_fid {
+       struct list_head list;   /* list of fids associated with a dentry */
+       struct list_head active; /* XXX - debug */
+
+       u32 fid;
+       unsigned char fidopen;    /* set when fid is opened */
+       unsigned char fidcreate;  /* set when fid was just created */
+       unsigned char fidclunked; /* set when fid has already been clunked */
+
+       struct v9fs_qid qid;
+       u32 iounit;
+
+       /* readdir stuff */
+       int rdir_fpos;
+       loff_t rdir_pos;
+       struct v9fs_fcall *rdir_fcall;
+
+       /* management stuff */
+       pid_t pid;              /* thread associated with this fid */
+       uid_t uid;              /* user associated with this fid */
+
+       /* private data */
+       struct file *filp;      /* backpointer to File struct for open files */
+       struct v9fs_session_info *v9ses;        /* session info for this FID */
+};
+
+struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry, int type);
+void v9fs_fid_destroy(struct v9fs_fid *fid);
+struct v9fs_fid *v9fs_fid_create(struct dentry *);
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
new file mode 100644 (file)
index 0000000..8835b57
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * linux/fs/9p/mux.c
+ *
+ * Protocol Multiplexer
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.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 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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kthread.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "transport.h"
+#include "conv.h"
+#include "mux.h"
+
+/**
+ * dprintcond - print condition of session info
+ * @v9ses: session info structure
+ * @req: RPC request structure
+ *
+ */
+
+static inline int
+dprintcond(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+{
+       dprintk(DEBUG_MUX, "condition: %d, %p\n", v9ses->transport->status,
+               req->rcall);
+       return 0;
+}
+
+/**
+ * xread - force read of a certain number of bytes
+ * @v9ses: session info structure
+ * @ptr: pointer to buffer
+ * @sz: number of bytes to read
+ *
+ * Chuck Cranor CS-533 project1
+ */
+
+static int xread(struct v9fs_session_info *v9ses, void *ptr, unsigned long sz)
+{
+       int rd = 0;
+       int ret = 0;
+       while (rd < sz) {
+               ret = v9ses->transport->read(v9ses->transport, ptr, sz - rd);
+               if (ret <= 0) {
+                       dprintk(DEBUG_ERROR, "xread errno %d\n", ret);
+                       return ret;
+               }
+               rd += ret;
+               ptr += ret;
+       }
+       return (rd);
+}
+
+/**
+ * read_message - read a full 9P2000 fcall packet
+ * @v9ses: session info structure
+ * @rcall: fcall structure to read into
+ * @rcalllen: size of fcall buffer
+ *
+ */
+
+static int
+read_message(struct v9fs_session_info *v9ses,
+            struct v9fs_fcall *rcall, int rcalllen)
+{
+       unsigned char buf[4];
+       void *data;
+       int size = 0;
+       int res = 0;
+
+       res = xread(v9ses, buf, sizeof(buf));
+       if (res < 0) {
+               dprintk(DEBUG_ERROR,
+                       "Reading of count field failed returned: %d\n", res);
+               return res;
+       }
+
+       if (res < 4) {
+               dprintk(DEBUG_ERROR,
+                       "Reading of count field failed returned: %d\n", res);
+               return -EIO;
+       }
+
+       size = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+       dprintk(DEBUG_MUX, "got a packet count: %d\n", size);
+
+       /* adjust for the four bytes of size */
+       size -= 4;
+
+       if (size > v9ses->maxdata) {
+               dprintk(DEBUG_ERROR, "packet too big: %d\n", size);
+               return -E2BIG;
+       }
+
+       data = kmalloc(size, GFP_KERNEL);
+       if (!data) {
+               eprintk(KERN_WARNING, "out of memory\n");
+               return -ENOMEM;
+       }
+
+       res = xread(v9ses, data, size);
+       if (res < size) {
+               dprintk(DEBUG_ERROR, "Reading of fcall failed returned: %d\n",
+                       res);
+               kfree(data);
+               return res;
+       }
+
+       /* we now have an in-memory string that is the reply.
+        * deserialize it. There is very little to go wrong at this point
+        * save for v9fs_alloc errors.
+        */
+       res = v9fs_deserialize_fcall(v9ses, size, data, v9ses->maxdata,
+                                    rcall, rcalllen);
+
+       kfree(data);
+
+       if (res < 0)
+               return res;
+
+       return 0;
+}
+
+/**
+ * v9fs_recv - receive an RPC response for a particular tag
+ * @v9ses: session info structure
+ * @req: RPC request structure
+ *
+ */
+
+static int v9fs_recv(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+{
+       int ret = 0;
+
+       dprintk(DEBUG_MUX, "waiting for response: %d\n", req->tcall->tag);
+       ret = wait_event_interruptible(v9ses->read_wait,
+                      ((v9ses->transport->status != Connected) ||
+                       (req->rcall != 0) || (req->err < 0) ||
+                       dprintcond(v9ses, req)));
+
+       dprintk(DEBUG_MUX, "got it: rcall %p\n", req->rcall);
+
+       spin_lock(&v9ses->muxlock);
+       list_del(&req->next);
+       spin_unlock(&v9ses->muxlock);
+
+       if (req->err < 0)
+               return req->err;
+
+       if (v9ses->transport->status == Disconnected)
+               return -ECONNRESET;
+
+       return ret;
+}
+
+/**
+ * v9fs_send - send a 9P request
+ * @v9ses: session info structure
+ * @req: RPC request to send
+ *
+ */
+
+static int v9fs_send(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+{
+       int ret = -1;
+       void *data = NULL;
+       struct v9fs_fcall *tcall = req->tcall;
+
+       data = kmalloc(v9ses->maxdata + V9FS_IOHDRSZ, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       tcall->size = 0;        /* enforce size recalculation */
+       ret =
+           v9fs_serialize_fcall(v9ses, tcall, data,
+                                v9ses->maxdata + V9FS_IOHDRSZ);
+       if (ret < 0)
+               goto free_data;
+
+       spin_lock(&v9ses->muxlock);
+       list_add(&req->next, &v9ses->mux_fcalls);
+       spin_unlock(&v9ses->muxlock);
+
+       dprintk(DEBUG_MUX, "sending message: tag %d size %d\n", tcall->tag,
+               tcall->size);
+       ret = v9ses->transport->write(v9ses->transport, data, tcall->size);
+
+       if (ret != tcall->size) {
+               spin_lock(&v9ses->muxlock);
+               list_del(&req->next);
+               kfree(req->rcall);
+
+               spin_unlock(&v9ses->muxlock);
+               if (ret >= 0)
+                       ret = -EREMOTEIO;
+       } else
+               ret = 0;
+
+      free_data:
+       kfree(data);
+       return ret;
+}
+
+/**
+ * v9fs_mux_rpc - send a request, receive a response
+ * @v9ses: session info structure
+ * @tcall: fcall to send
+ * @rcall: buffer to place response into
+ *
+ */
+
+long
+v9fs_mux_rpc(struct v9fs_session_info *v9ses, struct v9fs_fcall *tcall,
+            struct v9fs_fcall **rcall)
+{
+       int tid = -1;
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_rpcreq req;
+       int ret = -1;
+
+       if (!v9ses)
+               return -EINVAL;
+
+       if (!v9ses->transport || v9ses->transport->status != Connected)
+               return -EIO;
+
+       if (rcall)
+               *rcall = NULL;
+
+       if (tcall->id != TVERSION) {
+               tid = v9fs_get_idpool(&v9ses->tidpool);
+               if (tid < 0)
+                       return -ENOMEM;
+       }
+
+       tcall->tag = tid;
+
+       req.tcall = tcall;
+       req.err = 0;
+       req.rcall = NULL;
+
+       ret = v9fs_send(v9ses, &req);
+
+       if (ret < 0) {
+               if (tcall->id != TVERSION)
+                       v9fs_put_idpool(tid, &v9ses->tidpool);
+               dprintk(DEBUG_MUX, "error %d\n", ret);
+               return ret;
+       }
+
+       ret = v9fs_recv(v9ses, &req);
+
+       fcall = req.rcall;
+
+       dprintk(DEBUG_MUX, "received: tag=%x, ret=%d\n", tcall->tag, ret);
+       if (ret == -ERESTARTSYS) {
+               if (v9ses->transport->status != Disconnected
+                   && tcall->id != TFLUSH) {
+                       unsigned long flags;
+
+                       dprintk(DEBUG_MUX, "flushing the tag: %d\n",
+                               tcall->tag);
+                       clear_thread_flag(TIF_SIGPENDING);
+                       v9fs_t_flush(v9ses, tcall->tag);
+                       spin_lock_irqsave(&current->sighand->siglock, flags);
+                       recalc_sigpending();
+                       spin_unlock_irqrestore(&current->sighand->siglock,
+                                              flags);
+                       dprintk(DEBUG_MUX, "flushing done\n");
+               }
+
+               goto release_req;
+       } else if (ret < 0)
+               goto release_req;
+
+       if (!fcall)
+               ret = -EIO;
+       else {
+               if (fcall->id == RERROR) {
+                       ret = v9fs_errstr2errno(fcall->params.rerror.error);
+                       if (ret == 0) { /* string match failed */
+                               if (fcall->params.rerror.errno)
+                                       ret = -(fcall->params.rerror.errno);
+                               else
+                                       ret = -ESERVERFAULT;
+                       }
+               } else if (fcall->id != tcall->id + 1) {
+                       dprintk(DEBUG_ERROR,
+                               "fcall mismatch: expected %d, got %d\n",
+                               tcall->id + 1, fcall->id);
+                       ret = -EIO;
+               }
+       }
+
+      release_req:
+       if (tcall->id != TVERSION)
+               v9fs_put_idpool(tid, &v9ses->tidpool);
+       if (rcall)
+               *rcall = fcall;
+       else
+               kfree(fcall);
+
+       return ret;
+}
+
+/**
+ * v9fs_mux_cancel_requests - cancels all pending requests
+ *
+ * @v9ses: session info structure
+ * @err: error code to return to the requests
+ */
+void v9fs_mux_cancel_requests(struct v9fs_session_info *v9ses, int err)
+{
+       struct v9fs_rpcreq *rptr;
+       struct v9fs_rpcreq *rreq;
+
+       dprintk(DEBUG_MUX, " %d\n", err);
+       spin_lock(&v9ses->muxlock);
+       list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) {
+               rreq->err = err;
+       }
+       spin_unlock(&v9ses->muxlock);
+       wake_up_all(&v9ses->read_wait);
+}
+
+/**
+ * v9fs_recvproc - kproc to handle demultiplexing responses
+ * @data: session info structure
+ *
+ */
+
+static int v9fs_recvproc(void *data)
+{
+       struct v9fs_session_info *v9ses = (struct v9fs_session_info *)data;
+       struct v9fs_fcall *rcall = NULL;
+       struct v9fs_rpcreq *rptr;
+       struct v9fs_rpcreq *req;
+       struct v9fs_rpcreq *rreq;
+       int err = 0;
+
+       allow_signal(SIGKILL);
+       set_current_state(TASK_INTERRUPTIBLE);
+       complete(&v9ses->proccmpl);
+       while (!kthread_should_stop() && err >= 0) {
+               req = rptr = rreq = NULL;
+
+               rcall = kmalloc(v9ses->maxdata + V9FS_IOHDRSZ, GFP_KERNEL);
+               if (!rcall) {
+                       eprintk(KERN_ERR, "no memory for buffers\n");
+                       break;
+               }
+
+               err = read_message(v9ses, rcall, v9ses->maxdata + V9FS_IOHDRSZ);
+               spin_lock(&v9ses->muxlock);
+               if (err < 0) {
+                       list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) {
+                               rreq->err = err;
+                       }
+                       if(err != -ERESTARTSYS)
+                               eprintk(KERN_ERR,
+                                       "Transport error while reading message %d\n", err);
+               } else {
+                       list_for_each_entry_safe(rreq, rptr, &v9ses->mux_fcalls, next) {
+                               if (rreq->tcall->tag == rcall->tag) {
+                                       req = rreq;
+                                       req->rcall = rcall;
+                                       break;
+                               }
+                       }
+               }
+
+               if (req && (req->tcall->id == TFLUSH)) {
+                       struct v9fs_rpcreq *treq = NULL;
+                       list_for_each_entry_safe(treq, rptr, &v9ses->mux_fcalls, next) {
+                               if (treq->tcall->tag ==
+                                   req->tcall->params.tflush.oldtag) {
+                                       list_del(&rptr->next);
+                                       kfree(treq->rcall);
+                                       break;
+                               }
+                       }
+               }
+
+               spin_unlock(&v9ses->muxlock);
+
+               if (!req) {
+                       if (err >= 0)
+                               dprintk(DEBUG_ERROR,
+                                       "unexpected response: id %d tag %d\n",
+                                       rcall->id, rcall->tag);
+
+                       kfree(rcall);
+               }
+
+               wake_up_all(&v9ses->read_wait);
+               set_current_state(TASK_INTERRUPTIBLE);
+       }
+
+       v9ses->transport->close(v9ses->transport);
+
+       /* Inform all pending processes about the failure */
+       wake_up_all(&v9ses->read_wait);
+
+       if (signal_pending(current))
+               complete(&v9ses->proccmpl);
+
+       dprintk(DEBUG_MUX, "recvproc: end\n");
+       v9ses->recvproc = NULL;
+
+       return err >= 0;
+}
+
+/**
+ * v9fs_mux_init - initialize multiplexer (spawn kproc)
+ * @v9ses: session info structure
+ * @dev_name: mount device information (to create unique kproc)
+ *
+ */
+
+int v9fs_mux_init(struct v9fs_session_info *v9ses, const char *dev_name)
+{
+       char procname[60];
+
+       strncpy(procname, dev_name, sizeof(procname));
+       procname[sizeof(procname) - 1] = 0;
+
+       init_waitqueue_head(&v9ses->read_wait);
+       init_completion(&v9ses->fcread);
+       init_completion(&v9ses->proccmpl);
+       spin_lock_init(&v9ses->muxlock);
+       INIT_LIST_HEAD(&v9ses->mux_fcalls);
+       v9ses->recvproc = NULL;
+       v9ses->curfcall = NULL;
+
+       v9ses->recvproc = kthread_create(v9fs_recvproc, v9ses,
+                                        "v9fs_recvproc %s", procname);
+
+       if (IS_ERR(v9ses->recvproc)) {
+               eprintk(KERN_ERR, "cannot create receiving thread\n");
+               v9fs_session_close(v9ses);
+               return -ECONNABORTED;
+       }
+
+       wake_up_process(v9ses->recvproc);
+       wait_for_completion(&v9ses->proccmpl);
+
+       return 0;
+}
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
new file mode 100644 (file)
index 0000000..4994cb1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * linux/fs/9p/mux.h
+ *
+ * Multiplexer Definitions
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+/* structure to manage each RPC transaction */
+
+struct v9fs_rpcreq {
+       struct v9fs_fcall *tcall;
+       struct v9fs_fcall *rcall;
+       int err;        /* error code if response failed */
+
+       /* XXX - could we put scatter/gather buffers here? */
+
+       struct list_head next;
+};
+
+int v9fs_mux_init(struct v9fs_session_info *v9ses, const char *dev_name);
+long v9fs_mux_rpc(struct v9fs_session_info *v9ses,
+                 struct v9fs_fcall *tcall, struct v9fs_fcall **rcall);
+void v9fs_mux_cancel_requests(struct v9fs_session_info *v9ses, int err);
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
new file mode 100644 (file)
index 0000000..63b58ce
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * linux/fs/9p/trans_fd.c
+ *
+ * File Descriptor Transport Layer
+ *
+ *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+#include <linux/file.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "transport.h"
+
+struct v9fs_trans_fd {
+       struct file *in_file;
+       struct file *out_file;
+};
+
+/**
+ * v9fs_fd_recv - receive from a socket
+ * @v9ses: session information
+ * @v: buffer to receive data into
+ * @len: size of receive buffer
+ *
+ */
+
+static int v9fs_fd_recv(struct v9fs_transport *trans, void *v, int len)
+{
+       struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
+
+       if (!trans || trans->status != Connected || !ts)
+               return -EIO;
+
+       return kernel_read(ts->in_file, ts->in_file->f_pos, v, len);
+}
+
+/**
+ * v9fs_fd_send - send to a socket
+ * @v9ses: session information
+ * @v: buffer to send data from
+ * @len: size of send buffer
+ *
+ */
+
+static int v9fs_fd_send(struct v9fs_transport *trans, void *v, int len)
+{
+       struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
+       mm_segment_t oldfs = get_fs();
+       int ret = 0;
+
+       if (!trans || trans->status != Connected || !ts)
+               return -EIO;
+
+       set_fs(get_ds());
+       /* The cast to a user pointer is valid due to the set_fs() */
+       ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos);
+       set_fs(oldfs);
+
+       return ret;
+}
+
+/**
+ * v9fs_fd_init - initialize file descriptor transport
+ * @v9ses: session information
+ * @addr: address of server to mount
+ * @data: mount options
+ *
+ */
+
+static int
+v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+{
+       struct v9fs_trans_fd *ts = NULL;
+       struct v9fs_transport *trans = v9ses->transport;
+
+       if((v9ses->wfdno == ~0) || (v9ses->rfdno == ~0)) {
+               printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+               return -ENOPROTOOPT;
+       }
+
+       sema_init(&trans->writelock, 1);
+       sema_init(&trans->readlock, 1);
+
+       ts = kmalloc(sizeof(struct v9fs_trans_fd), GFP_KERNEL);
+
+       if (!ts)
+               return -ENOMEM;
+
+       ts->in_file = fget( v9ses->rfdno );
+       ts->out_file = fget( v9ses->wfdno );
+
+       if (!ts->in_file || !ts->out_file) {
+               if (ts->in_file)
+                       fput(ts->in_file);
+
+               if (ts->out_file)
+                       fput(ts->out_file);
+
+               kfree(ts);
+               return -EIO;
+       }
+
+       trans->priv = ts;
+       trans->status = Connected;
+
+       return 0;
+}
+
+
+/**
+ * v9fs_fd_close - shutdown file descriptor
+ * @trans: private socket structure
+ *
+ */
+
+static void v9fs_fd_close(struct v9fs_transport *trans)
+{
+       struct v9fs_trans_fd *ts;
+
+       if (!trans)
+               return;
+
+       trans->status = Disconnected;
+       ts = trans->priv;
+
+       if (!ts)
+               return;
+
+       if (ts->in_file)
+               fput(ts->in_file);
+
+       if (ts->out_file)
+               fput(ts->out_file);
+
+       kfree(ts);
+}
+
+struct v9fs_transport v9fs_trans_fd = {
+       .init = v9fs_fd_init,
+       .write = v9fs_fd_send,
+       .read = v9fs_fd_recv,
+       .close = v9fs_fd_close,
+};
+
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c
new file mode 100644 (file)
index 0000000..01e26f0
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * linux/fs/9p/trans_socket.c
+ *
+ * Socket Transport Layer
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
+ *  Copyright (C) 1995, 1996 by Olaf Kirch <okir@monad.swb.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <asm/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "transport.h"
+
+#define V9FS_PORT 564
+
+struct v9fs_trans_sock {
+       struct socket *s;
+};
+
+/**
+ * v9fs_sock_recv - receive from a socket
+ * @v9ses: session information
+ * @v: buffer to receive data into
+ * @len: size of receive buffer
+ *
+ */
+
+static int v9fs_sock_recv(struct v9fs_transport *trans, void *v, int len)
+{
+       struct msghdr msg;
+       struct kvec iov;
+       int result;
+       mm_segment_t oldfs;
+       struct v9fs_trans_sock *ts = trans ? trans->priv : NULL;
+
+       if (trans->status == Disconnected)
+               return -EREMOTEIO;
+
+       result = -EINVAL;
+
+       oldfs = get_fs();
+       set_fs(get_ds());
+
+       iov.iov_base = v;
+       iov.iov_len = len;
+       msg.msg_name = NULL;
+       msg.msg_namelen = 0;
+       msg.msg_iovlen = 1;
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_namelen = 0;
+       msg.msg_flags = MSG_NOSIGNAL;
+
+       result = kernel_recvmsg(ts->s, &msg, &iov, 1, len, 0);
+
+       dprintk(DEBUG_TRANS, "socket state %d\n", ts->s->state);
+       set_fs(oldfs);
+
+       if (result <= 0) {
+               if (result != -ERESTARTSYS)
+                       trans->status = Disconnected;
+       }
+
+       return result;
+}
+
+/**
+ * v9fs_sock_send - send to a socket
+ * @v9ses: session information
+ * @v: buffer to send data from
+ * @len: size of send buffer
+ *
+ */
+
+static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len)
+{
+       struct kvec iov;
+       struct msghdr msg;
+       int result = -1;
+       mm_segment_t oldfs;
+       struct v9fs_trans_sock *ts = trans ? trans->priv : NULL;
+
+       dprintk(DEBUG_TRANS, "Sending packet size %d (%x)\n", len, len);
+       dump_data(v, len);
+
+       down(&trans->writelock);
+
+       oldfs = get_fs();
+       set_fs(get_ds());
+       iov.iov_base = v;
+       iov.iov_len = len;
+       msg.msg_name = NULL;
+       msg.msg_namelen = 0;
+       msg.msg_iovlen = 1;
+       msg.msg_control = NULL;
+       msg.msg_controllen = 0;
+       msg.msg_namelen = 0;
+       msg.msg_flags = MSG_NOSIGNAL;
+       result = kernel_sendmsg(ts->s, &msg, &iov, 1, len);
+       set_fs(oldfs);
+
+       if (result < 0) {
+               if (result != -ERESTARTSYS)
+                       trans->status = Disconnected;
+       }
+
+       up(&trans->writelock);
+       return result;
+}
+
+/**
+ * v9fs_tcp_init - initialize TCP socket
+ * @v9ses: session information
+ * @addr: address of server to mount
+ * @data: mount options
+ *
+ */
+
+static int
+v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+{
+       struct socket *csocket = NULL;
+       struct sockaddr_in sin_server;
+       int rc = 0;
+       struct v9fs_trans_sock *ts = NULL;
+       struct v9fs_transport *trans = v9ses->transport;
+
+       sema_init(&trans->writelock, 1);
+       sema_init(&trans->readlock, 1);
+
+       ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
+
+       if (!ts)
+               return -ENOMEM;
+
+       trans->priv = ts;
+       ts->s = NULL;
+
+       if (!addr)
+               return -EINVAL;
+
+       dprintk(DEBUG_TRANS, "Connecting to %s\n", addr);
+
+       sin_server.sin_family = AF_INET;
+       sin_server.sin_addr.s_addr = in_aton(addr);
+       sin_server.sin_port = htons(v9ses->port);
+       sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+       rc = csocket->ops->connect(csocket,
+                                  (struct sockaddr *)&sin_server,
+                                  sizeof(struct sockaddr_in), 0);
+       if (rc < 0) {
+               eprintk(KERN_ERR,
+                       "v9fs_trans_tcp: problem connecting socket to %s\n",
+                       addr);
+               return rc;
+       }
+       csocket->sk->sk_allocation = GFP_NOIO;
+       ts->s = csocket;
+       trans->status = Connected;
+
+       return 0;
+}
+
+/**
+ * v9fs_unix_init - initialize UNIX domain socket
+ * @v9ses: session information
+ * @dev_name: path to named pipe
+ * @data: mount options
+ *
+ */
+
+static int
+v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
+              char *data)
+{
+       int rc;
+       struct socket *csocket;
+       struct sockaddr_un sun_server;
+       struct v9fs_transport *trans;
+       struct v9fs_trans_sock *ts;
+
+       rc = 0;
+       csocket = NULL;
+       trans = v9ses->transport;
+
+       if (strlen(dev_name) > UNIX_PATH_MAX) {
+               eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
+                       dev_name);
+               return -ENOMEM;
+       }
+
+       ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
+       if (!ts)
+               return -ENOMEM;
+
+       trans->priv = ts;
+       ts->s = NULL;
+
+       sema_init(&trans->writelock, 1);
+       sema_init(&trans->readlock, 1);
+
+       sun_server.sun_family = PF_UNIX;
+       strcpy(sun_server.sun_path, dev_name);
+       sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+       rc = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+               sizeof(struct sockaddr_un) - 1, 0);     /* -1 *is* important */
+       if (rc < 0) {
+               eprintk(KERN_ERR,
+                       "v9fs_trans_unix: problem connecting socket: %s: %d\n",
+                       dev_name, rc);
+               return rc;
+       }
+       csocket->sk->sk_allocation = GFP_NOIO;
+       ts->s = csocket;
+       trans->status = Connected;
+
+       return 0;
+}
+
+/**
+ * v9fs_sock_close - shutdown socket
+ * @trans: private socket structure
+ *
+ */
+
+static void v9fs_sock_close(struct v9fs_transport *trans)
+{
+       struct v9fs_trans_sock *ts;
+
+       if (!trans)
+               return;
+
+       ts = trans->priv;
+
+       if ((ts) && (ts->s)) {
+               dprintk(DEBUG_TRANS, "closing the socket %p\n", ts->s);
+               sock_release(ts->s);
+               ts->s = NULL;
+               trans->status = Disconnected;
+               dprintk(DEBUG_TRANS, "socket closed\n");
+       }
+
+       if (ts)
+               kfree(ts);
+
+       trans->priv = NULL;
+}
+
+struct v9fs_transport v9fs_trans_tcp = {
+       .init = v9fs_tcp_init,
+       .write = v9fs_sock_send,
+       .read = v9fs_sock_recv,
+       .close = v9fs_sock_close,
+};
+
+struct v9fs_transport v9fs_trans_unix = {
+       .init = v9fs_unix_init,
+       .write = v9fs_sock_send,
+       .read = v9fs_sock_recv,
+       .close = v9fs_sock_close,
+};
diff --git a/fs/9p/transport.h b/fs/9p/transport.h
new file mode 100644 (file)
index 0000000..9e9cd41
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * linux/fs/9p/transport.h
+ *
+ * Transport Definition
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+enum v9fs_transport_status {
+       Connected,
+       Disconnected,
+       Hung,
+};
+
+struct v9fs_transport {
+       enum v9fs_transport_status status;
+       struct semaphore writelock;
+       struct semaphore readlock;
+       void *priv;
+
+       int (*init) (struct v9fs_session_info *, const char *, char *);
+       int (*write) (struct v9fs_transport *, void *, int);
+       int (*read) (struct v9fs_transport *, void *, int);
+       void (*close) (struct v9fs_transport *);
+};
+
+extern struct v9fs_transport v9fs_trans_tcp;
+extern struct v9fs_transport v9fs_trans_unix;
+extern struct v9fs_transport v9fs_trans_fd;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
new file mode 100644 (file)
index 0000000..13bdbba
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *  linux/fs/9p/v9fs.c
+ *
+ *  This file contains functions assisting in mapping VFS to 9P2000
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/parser.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "transport.h"
+#include "mux.h"
+#include "conv.h"
+
+/* TODO: sysfs or debugfs interface */
+int v9fs_debug_level = 0;      /* feature-rific global debug level  */
+
+/*
+  * Option Parsing (code inspired by NFS code)
+  *
+  */
+
+enum {
+       /* Options that take integer arguments */
+       Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug,
+       Opt_rfdno, Opt_wfdno,
+       /* String options */
+       Opt_name, Opt_remotename,
+       /* Options that take no arguments */
+       Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+       /* Error token */
+       Opt_err
+};
+
+static match_table_t tokens = {
+       {Opt_port, "port=%u"},
+       {Opt_msize, "msize=%u"},
+       {Opt_uid, "uid=%u"},
+       {Opt_gid, "gid=%u"},
+       {Opt_afid, "afid=%u"},
+       {Opt_rfdno, "rfdno=%u"},
+       {Opt_wfdno, "wfdno=%u"},
+       {Opt_debug, "debug=%u"},
+       {Opt_name, "name=%s"},
+       {Opt_remotename, "aname=%s"},
+       {Opt_unix, "proto=unix"},
+       {Opt_tcp, "proto=tcp"},
+       {Opt_fd, "proto=fd"},
+       {Opt_tcp, "tcp"},
+       {Opt_unix, "unix"},
+       {Opt_fd, "fd"},
+       {Opt_legacy, "noextend"},
+       {Opt_nodevmap, "nodevmap"},
+       {Opt_err, NULL}
+};
+
+/*
+ *  Parse option string.
+ */
+
+/**
+ * v9fs_parse_options - parse mount options into session structure
+ * @options: options string passed from mount
+ * @v9ses: existing v9fs session information
+ *
+ */
+
+static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
+{
+       char *p;
+       substring_t args[MAX_OPT_ARGS];
+       int option;
+       int ret;
+
+       /* setup defaults */
+       v9ses->port = V9FS_PORT;
+       v9ses->maxdata = 9000;
+       v9ses->proto = PROTO_TCP;
+       v9ses->extended = 1;
+       v9ses->afid = ~0;
+       v9ses->debug = 0;
+       v9ses->rfdno = ~0;
+       v9ses->wfdno = ~0;
+
+       if (!options)
+               return;
+
+       while ((p = strsep(&options, ",")) != NULL) {
+               int token;
+               if (!*p)
+                       continue;
+               token = match_token(p, tokens, args);
+               if (token < Opt_name) {
+                       if ((ret = match_int(&args[0], &option)) < 0) {
+                               dprintk(DEBUG_ERROR,
+                                       "integer field, but no integer?\n");
+                               continue;
+                       }
+
+               }
+               switch (token) {
+               case Opt_port:
+                       v9ses->port = option;
+                       break;
+               case Opt_msize:
+                       v9ses->maxdata = option;
+                       break;
+               case Opt_uid:
+                       v9ses->uid = option;
+                       break;
+               case Opt_gid:
+                       v9ses->gid = option;
+                       break;
+               case Opt_afid:
+                       v9ses->afid = option;
+                       break;
+               case Opt_rfdno:
+                       v9ses->rfdno = option;
+                       break;
+               case Opt_wfdno:
+                       v9ses->wfdno = option;
+                       break;
+               case Opt_debug:
+                       v9ses->debug = option;
+                       break;
+               case Opt_tcp:
+                       v9ses->proto = PROTO_TCP;
+                       break;
+               case Opt_unix:
+                       v9ses->proto = PROTO_UNIX;
+                       break;
+               case Opt_fd:
+                       v9ses->proto = PROTO_FD;
+                       break;
+               case Opt_name:
+                       match_strcpy(v9ses->name, &args[0]);
+                       break;
+               case Opt_remotename:
+                       match_strcpy(v9ses->remotename, &args[0]);
+                       break;
+               case Opt_legacy:
+                       v9ses->extended = 0;
+                       break;
+               case Opt_nodevmap:
+                       v9ses->nodev = 1;
+                       break;
+               default:
+                       continue;
+               }
+       }
+}
+
+/**
+ * v9fs_inode2v9ses - safely extract v9fs session info from super block
+ * @inode: inode to extract information from
+ *
+ * Paranoid function to extract v9ses information from superblock,
+ * if anything is missing it will report an error.
+ *
+ */
+
+struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
+{
+       return (inode->i_sb->s_fs_info);
+}
+
+/**
+ * v9fs_get_idpool - allocate numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ *            the lock included in struct idr?
+ */
+
+int v9fs_get_idpool(struct v9fs_idpool *p)
+{
+       int i = 0;
+       int error;
+
+retry:
+       if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
+               return 0;
+
+       if (down_interruptible(&p->lock) == -EINTR) {
+               eprintk(KERN_WARNING, "Interrupted while locking\n");
+               return -1;
+       }
+
+       error = idr_get_new(&p->pool, NULL, &i);
+       up(&p->lock);
+
+       if (error == -EAGAIN)
+               goto retry;
+       else if (error)
+               return -1;
+
+       return i;
+}
+
+/**
+ * v9fs_put_idpool - release numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ *            the lock included in struct idr?
+ */
+
+void v9fs_put_idpool(int id, struct v9fs_idpool *p)
+{
+       if (down_interruptible(&p->lock) == -EINTR) {
+               eprintk(KERN_WARNING, "Interrupted while locking\n");
+               return;
+       }
+       idr_remove(&p->pool, id);
+       up(&p->lock);
+}
+
+/**
+ * v9fs_session_init - initialize session
+ * @v9ses: session information structure
+ * @dev_name: device being mounted
+ * @data: options
+ *
+ */
+
+int
+v9fs_session_init(struct v9fs_session_info *v9ses,
+                 const char *dev_name, char *data)
+{
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_transport *trans_proto;
+       int n = 0;
+       int newfid = -1;
+       int retval = -EINVAL;
+
+       v9ses->name = __getname();
+       if (!v9ses->name)
+               return -ENOMEM;
+
+       v9ses->remotename = __getname();
+       if (!v9ses->remotename) {
+               putname(v9ses->name);
+               return -ENOMEM;
+       }
+
+       strcpy(v9ses->name, V9FS_DEFUSER);
+       strcpy(v9ses->remotename, V9FS_DEFANAME);
+
+       v9fs_parse_options(data, v9ses);
+
+       /* set global debug level */
+       v9fs_debug_level = v9ses->debug;
+
+       /* id pools that are session-dependent: FIDs and TIDs */
+       idr_init(&v9ses->fidpool.pool);
+       init_MUTEX(&v9ses->fidpool.lock);
+       idr_init(&v9ses->tidpool.pool);
+       init_MUTEX(&v9ses->tidpool.lock);
+
+
+       switch (v9ses->proto) {
+       case PROTO_TCP:
+               trans_proto = &v9fs_trans_tcp;
+               break;
+       case PROTO_UNIX:
+               trans_proto = &v9fs_trans_unix;
+               *v9ses->remotename = 0;
+               break;
+       case PROTO_FD:
+               trans_proto = &v9fs_trans_fd;
+               *v9ses->remotename = 0;
+               break;
+       default:
+               printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
+               retval = -ENOPROTOOPT;
+               goto SessCleanUp;
+       };
+
+       v9ses->transport = trans_proto;
+
+       if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) {
+               eprintk(KERN_ERR, "problem initializing transport\n");
+               goto SessCleanUp;
+       }
+
+       v9ses->inprogress = 0;
+       v9ses->shutdown = 0;
+       v9ses->session_hung = 0;
+
+       if ((retval = v9fs_mux_init(v9ses, dev_name)) < 0) {
+               dprintk(DEBUG_ERROR, "problem initializing mux\n");
+               goto SessCleanUp;
+       }
+
+       if (v9ses->afid == ~0) {
+               if (v9ses->extended)
+                       retval =
+                           v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u",
+                                          &fcall);
+               else
+                       retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000",
+                                               &fcall);
+
+               if (retval < 0) {
+                       dprintk(DEBUG_ERROR, "v9fs_t_version failed\n");
+                       goto FreeFcall;
+               }
+
+               /* Really should check for 9P1 and report error */
+               if (!strcmp(fcall->params.rversion.version, "9P2000.u")) {
+                       dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
+                       v9ses->extended = 1;
+               } else {
+                       dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
+                       v9ses->extended = 0;
+               }
+
+               n = fcall->params.rversion.msize;
+               kfree(fcall);
+
+               if (n < v9ses->maxdata)
+                       v9ses->maxdata = n;
+       }
+
+       newfid = v9fs_get_idpool(&v9ses->fidpool);
+       if (newfid < 0) {
+               eprintk(KERN_WARNING, "couldn't allocate FID\n");
+               retval = -ENOMEM;
+               goto SessCleanUp;
+       }
+       /* it is a little bit ugly, but we have to prevent newfid */
+       /* being the same as afid, so if it is, get a new fid     */
+       if (v9ses->afid != ~0 && newfid == v9ses->afid) {
+               newfid = v9fs_get_idpool(&v9ses->fidpool);
+               if (newfid < 0) {
+                       eprintk(KERN_WARNING, "couldn't allocate FID\n");
+                       retval = -ENOMEM;
+                       goto SessCleanUp;
+               }
+       }
+
+       if ((retval =
+            v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid,
+                          v9ses->afid, NULL))
+           < 0) {
+               dprintk(DEBUG_ERROR, "cannot attach\n");
+               goto SessCleanUp;
+       }
+
+       if (v9ses->afid != ~0) {
+               if (v9fs_t_clunk(v9ses, v9ses->afid, NULL))
+                       dprintk(DEBUG_ERROR, "clunk failed\n");
+       }
+
+       return newfid;
+
+      FreeFcall:
+       kfree(fcall);
+
+      SessCleanUp:
+       v9fs_session_close(v9ses);
+       return retval;
+}
+
+/**
+ * v9fs_session_close - shutdown a session
+ * @v9ses: session information structure
+ *
+ */
+
+void v9fs_session_close(struct v9fs_session_info *v9ses)
+{
+       if (v9ses->recvproc) {
+               send_sig(SIGKILL, v9ses->recvproc, 1);
+               wait_for_completion(&v9ses->proccmpl);
+       }
+
+       if (v9ses->transport)
+               v9ses->transport->close(v9ses->transport);
+
+       putname(v9ses->name);
+       putname(v9ses->remotename);
+}
+
+/**
+ * v9fs_session_cancel - mark transport as disconnected
+ *     and cancel all pending requests.
+ */
+void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
+       v9ses->transport->status = Disconnected;
+       v9fs_mux_cancel_requests(v9ses, -EIO);
+}
+
+extern int v9fs_error_init(void);
+
+/**
+ * v9fs_init - Initialize module
+ *
+ */
+
+static int __init init_v9fs(void)
+{
+       v9fs_error_init();
+
+       printk(KERN_INFO "Installing v9fs 9P2000 file system support\n");
+
+       return register_filesystem(&v9fs_fs_type);
+}
+
+/**
+ * v9fs_init - shutdown module
+ *
+ */
+
+static void __exit exit_v9fs(void)
+{
+       unregister_filesystem(&v9fs_fs_type);
+}
+
+module_init(init_v9fs)
+module_exit(exit_v9fs)
+
+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
+MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
+MODULE_LICENSE("GPL");
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
new file mode 100644 (file)
index 0000000..45dcef4
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * V9FS definitions.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+/*
+  * Idpool structure provides lock and id management
+  *
+  */
+
+struct v9fs_idpool {
+       struct semaphore lock;
+       struct idr pool;
+};
+
+/*
+  * Session structure provides information for an opened session
+  *
+  */
+
+struct v9fs_session_info {
+       /* options */
+       unsigned int maxdata;
+       unsigned char extended; /* set to 1 if we are using UNIX extensions */
+       unsigned char nodev;    /* set to 1 if no disable device mapping */
+       unsigned short port;    /* port to connect to */
+       unsigned short debug;   /* debug level */
+       unsigned short proto;   /* protocol to use */
+       unsigned int afid;      /* authentication fid */
+       unsigned int rfdno;     /* read file descriptor number */
+       unsigned int wfdno;     /* write file descriptor number */
+
+
+       char *name;             /* user name to mount as */
+       char *remotename;       /* name of remote hierarchy being mounted */
+       unsigned int uid;       /* default uid/muid for legacy support */
+       unsigned int gid;       /* default gid for legacy support */
+
+       /* book keeping */
+       struct v9fs_idpool fidpool;     /* The FID pool for file descriptors */
+       struct v9fs_idpool tidpool;     /* The TID pool for transactions ids */
+
+       /* transport information */
+       struct v9fs_transport *transport;
+
+       int inprogress;         /* session in progress => true */
+       int shutdown;           /* session shutting down. no more attaches. */
+       unsigned char session_hung;
+
+       /* mux private data */
+       struct v9fs_fcall *curfcall;
+       wait_queue_head_t read_wait;
+       struct completion fcread;
+       struct completion proccmpl;
+       struct task_struct *recvproc;
+
+       spinlock_t muxlock;
+       struct list_head mux_fcalls;
+};
+
+/* possible values of ->proto */
+enum {
+       PROTO_TCP,
+       PROTO_UNIX,
+       PROTO_FD,
+};
+
+int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
+struct v9fs_session_info *v9fs_inode2v9ses(struct inode *);
+void v9fs_session_close(struct v9fs_session_info *v9ses);
+int v9fs_get_idpool(struct v9fs_idpool *p);
+void v9fs_put_idpool(int id, struct v9fs_idpool *p);
+void v9fs_session_cancel(struct v9fs_session_info *v9ses);
+
+#define V9FS_MAGIC 0x01021997
+
+/* other default globals */
+#define V9FS_PORT              564
+#define V9FS_DEFUSER   "nobody"
+#define V9FS_DEFANAME  ""
+
+/* inital pool sizes for fids and tags */
+#define V9FS_START_FIDS 8192
+#define V9FS_START_TIDS 256
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
new file mode 100644 (file)
index 0000000..2f2cea7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * V9FS VFS extensions.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+/* plan9 semantics are that created files are implicitly opened.
+ * But linux semantics are that you call create, then open.
+ * the plan9 approach is superior as it provides an atomic
+ * open.
+ * we track the create fid here. When the file is opened, if fidopen is
+ * non-zero, we use the fid and can skip some steps.
+ * there may be a better way to do this, but I don't know it.
+ * one BAD way is to clunk the fid on create, then open it again:
+ * you lose the atomicity of file open
+ */
+
+/* special case:
+ * unlink calls remove, which is an implicit clunk. So we have to track
+ * that kind of thing so that we don't try to clunk a dead fid.
+ */
+
+extern struct file_system_type v9fs_fs_type;
+extern struct file_operations v9fs_file_operations;
+extern struct file_operations v9fs_dir_operations;
+extern struct dentry_operations v9fs_dentry_operations;
+
+struct inode *v9fs_get_inode(struct super_block *sb, int mode);
+ino_t v9fs_qid2ino(struct v9fs_qid *qid);
+void v9fs_mistat2inode(struct v9fs_stat *, struct inode *,
+                      struct super_block *);
+int v9fs_dir_release(struct inode *inode, struct file *filp);
+int v9fs_file_open(struct inode *inode, struct file *file);
+void v9fs_inode2mistat(struct inode *inode, struct v9fs_stat *mistat);
+void v9fs_dentry_release(struct dentry *);
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
new file mode 100644 (file)
index 0000000..306c967
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  linux/fs/9p/vfs_dentry.c
+ *
+ * This file contians vfs dentry ops for the 9P2000 protocol.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/namei.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+/**
+ * v9fs_dentry_validate - VFS dcache hook to validate cache
+ * @dentry:  dentry that is being validated
+ * @nd: path data
+ *
+ * dcache really shouldn't be used for 9P2000 as at all due to
+ * potential attached semantics to directory traversal (walk).
+ *
+ * FUTURE: look into how to use dcache to allow multi-stage
+ * walks in Plan 9 & potential for better dcache operation which
+ * would remain valid for Plan 9 semantics.  Older versions
+ * had validation via stat for those interested.  However, since
+ * stat has the same approximate overhead as walk there really
+ * is no difference.  The only improvement would be from a
+ * time-decay cache like NFS has and that undermines the
+ * synchronous nature of 9P2000.
+ *
+ */
+
+static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
+{
+       struct dentry *dc = current->fs->pwd;
+
+       dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry);
+       if (v9fs_fid_lookup(dentry, FID_OP)) {
+               dprintk(DEBUG_VFS, "VALID\n");
+               return 1;
+       }
+
+       while (dc != NULL) {
+               if (dc == dentry) {
+                       dprintk(DEBUG_VFS, "VALID\n");
+                       return 1;
+               }
+               if (dc == dc->d_parent)
+                       break;
+
+               dc = dc->d_parent;
+       }
+
+       dprintk(DEBUG_VFS, "INVALID\n");
+       return 0;
+}
+
+/**
+ * v9fs_dentry_release - called when dentry is going to be freed
+ * @dentry:  dentry that is being release
+ *
+ */
+
+void v9fs_dentry_release(struct dentry *dentry)
+{
+       dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+       if (dentry->d_fsdata != NULL) {
+               struct list_head *fid_list = dentry->d_fsdata;
+               struct v9fs_fid *temp = NULL;
+               struct v9fs_fid *current_fid = NULL;
+               struct v9fs_fcall *fcall = NULL;
+
+               list_for_each_entry_safe(current_fid, temp, fid_list, list) {
+                       if (v9fs_t_clunk
+                           (current_fid->v9ses, current_fid->fid, &fcall))
+                               dprintk(DEBUG_ERROR, "clunk failed: %s\n",
+                                       FCALL_ERROR(fcall));
+
+                       v9fs_put_idpool(current_fid->fid,
+                                       &current_fid->v9ses->fidpool);
+
+                       kfree(fcall);
+                       v9fs_fid_destroy(current_fid);
+               }
+
+               kfree(dentry->d_fsdata);        /* free the list_head */
+       }
+}
+
+struct dentry_operations v9fs_dentry_operations = {
+       .d_revalidate = v9fs_dentry_validate,
+       .d_release = v9fs_dentry_release,
+};
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
new file mode 100644 (file)
index 0000000..c478a73
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * linux/fs/9p/vfs_dir.c
+ *
+ * This file contains vfs directory ops for the 9P2000 protocol.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+/**
+ * dt_type - return file type
+ * @mistat: mistat structure
+ *
+ */
+
+static inline int dt_type(struct v9fs_stat *mistat)
+{
+       unsigned long perm = mistat->mode;
+       int rettype = DT_REG;
+
+       if (perm & V9FS_DMDIR)
+               rettype = DT_DIR;
+       if (perm & V9FS_DMSYMLINK)
+               rettype = DT_LNK;
+
+       return rettype;
+}
+
+/**
+ * v9fs_dir_readdir - read a directory
+ * @filep: opened file structure
+ * @dirent: directory structure ???
+ * @filldir: function to populate directory structure ???
+ *
+ */
+
+static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct v9fs_fcall *fcall = NULL;
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+       struct v9fs_fid *file = filp->private_data;
+       unsigned int i, n;
+       int fid = -1;
+       int ret = 0;
+       struct v9fs_stat *mi = NULL;
+       int over = 0;
+
+       dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name);
+
+       fid = file->fid;
+
+       mi = kmalloc(v9ses->maxdata, GFP_KERNEL);
+       if (!mi)
+               return -ENOMEM;
+
+       if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) {
+               kfree(file->rdir_fcall);
+               file->rdir_fcall = NULL;
+       }
+
+       if (file->rdir_fcall) {
+               n = file->rdir_fcall->params.rread.count;
+               i = file->rdir_fpos;
+               while (i < n) {
+                       int s = v9fs_deserialize_stat(v9ses,
+                                 file->rdir_fcall->params.rread.data + i,
+                                 n - i, mi, v9ses->maxdata);
+
+                       if (s == 0) {
+                               dprintk(DEBUG_ERROR,
+                                       "error while deserializing mistat\n");
+                               ret = -EIO;
+                               goto FreeStructs;
+                       }
+
+                       over = filldir(dirent, mi->name, strlen(mi->name),
+                                   filp->f_pos, v9fs_qid2ino(&mi->qid),
+                                   dt_type(mi));
+
+                       if (over) {
+                               file->rdir_fpos = i;
+                               file->rdir_pos = filp->f_pos;
+                               break;
+                       }
+
+                       i += s;
+                       filp->f_pos += s;
+               }
+
+               if (!over) {
+                       kfree(file->rdir_fcall);
+                       file->rdir_fcall = NULL;
+               }
+       }
+
+       while (!over) {
+               ret = v9fs_t_read(v9ses, fid, filp->f_pos,
+                                           v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
+               if (ret < 0) {
+                       dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
+                               ret, fcall);
+                       goto FreeStructs;
+               } else if (ret == 0)
+                       break;
+
+               n = ret;
+               i = 0;
+               while (i < n) {
+                       int s = v9fs_deserialize_stat(v9ses,
+                                 fcall->params.rread.data + i, n - i, mi,
+                                 v9ses->maxdata);
+
+                       if (s == 0) {
+                               dprintk(DEBUG_ERROR,
+                                       "error while deserializing mistat\n");
+                               return -EIO;
+                       }
+
+                       over = filldir(dirent, mi->name, strlen(mi->name),
+                                   filp->f_pos, v9fs_qid2ino(&mi->qid),
+                                   dt_type(mi));
+
+                       if (over) {
+                               file->rdir_fcall = fcall;
+                               file->rdir_fpos = i;
+                               file->rdir_pos = filp->f_pos;
+                               fcall = NULL;
+                               break;
+                       }
+
+                       i += s;
+                       filp->f_pos += s;
+               }
+
+               kfree(fcall);
+       }
+
+      FreeStructs:
+       kfree(fcall);
+       kfree(mi);
+       return ret;
+}
+
+/**
+ * v9fs_dir_release - close a directory
+ * @inode: inode of the directory
+ * @filp: file pointer to a directory
+ *
+ */
+
+int v9fs_dir_release(struct inode *inode, struct file *filp)
+{
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+       struct v9fs_fid *fid = filp->private_data;
+       int fidnum = -1;
+
+       dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp,
+               fid->fid);
+       fidnum = fid->fid;
+
+       filemap_fdatawrite(inode->i_mapping);
+       filemap_fdatawait(inode->i_mapping);
+
+       if (fidnum >= 0) {
+               fid->fidopen--;
+               dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
+                       fid->fid);
+
+               if (fid->fidopen == 0) {
+                       if (v9fs_t_clunk(v9ses, fidnum, NULL))
+                               dprintk(DEBUG_ERROR, "clunk failed\n");
+
+                       v9fs_put_idpool(fid->fid, &v9ses->fidpool);
+               }
+
+               kfree(fid->rdir_fcall);
+
+               filp->private_data = NULL;
+               v9fs_fid_destroy(fid);
+       }
+
+       d_drop(filp->f_dentry);
+       return 0;
+}
+
+struct file_operations v9fs_dir_operations = {
+       .read = generic_read_dir,
+       .readdir = v9fs_dir_readdir,
+       .open = v9fs_file_open,
+       .release = v9fs_dir_release,
+};
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
new file mode 100644 (file)
index 0000000..1f8ae7d
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ *  linux/fs/9p/vfs_file.c
+ *
+ * This file contians vfs file ops for 9P2000.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "fid.h"
+
+/**
+ * v9fs_file_open - open a file (or directory)
+ * @inode: inode to be opened
+ * @file: file being opened
+ *
+ */
+
+int v9fs_file_open(struct inode *inode, struct file *file)
+{
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+       struct v9fs_fid *v9fid = v9fs_fid_lookup(file->f_dentry, FID_WALK);
+       struct v9fs_fid *v9newfid = NULL;
+       struct v9fs_fcall *fcall = NULL;
+       int open_mode = 0;
+       unsigned int iounit = 0;
+       int newfid = -1;
+       long result = -1;
+
+       dprintk(DEBUG_VFS, "inode: %p file: %p v9fid= %p\n", inode, file,
+               v9fid);
+
+       if (!v9fid) {
+               struct dentry *dentry = file->f_dentry;
+               dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
+
+               /* XXX - some duplication from lookup, generalize later */
+               /* basically vfs_lookup is too heavy weight */
+               v9fid = v9fs_fid_lookup(file->f_dentry, FID_OP);
+               if (!v9fid)
+                       return -EBADF;
+
+               v9fid = v9fs_fid_lookup(dentry->d_parent, FID_WALK);
+               if (!v9fid)
+                       return -EBADF;
+
+               newfid = v9fs_get_idpool(&v9ses->fidpool);
+               if (newfid < 0) {
+                       eprintk(KERN_WARNING, "newfid fails!\n");
+                       return -ENOSPC;
+               }
+
+               result =
+                   v9fs_t_walk(v9ses, v9fid->fid, newfid,
+                               (char *)file->f_dentry->d_name.name, NULL);
+               if (result < 0) {
+                       v9fs_put_idpool(newfid, &v9ses->fidpool);
+                       dprintk(DEBUG_ERROR, "rewalk didn't work\n");
+                       return -EBADF;
+               }
+
+               v9fid = v9fs_fid_create(dentry);
+               if (v9fid == NULL) {
+                       dprintk(DEBUG_ERROR, "couldn't insert\n");
+                       return -ENOMEM;
+               }
+               v9fid->fid = newfid;
+       }
+
+       if (v9fid->fidcreate) {
+               /* create case */
+               newfid = v9fid->fid;
+               iounit = v9fid->iounit;
+               v9fid->fidcreate = 0;
+       } else {
+               if (!S_ISDIR(inode->i_mode))
+                       newfid = v9fid->fid;
+               else {
+                       newfid = v9fs_get_idpool(&v9ses->fidpool);
+                       if (newfid < 0) {
+                               eprintk(KERN_WARNING, "allocation failed\n");
+                               return -ENOSPC;
+                       }
+                       /* This would be a somewhat critical clone */
+                       result =
+                           v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL,
+                                       &fcall);
+                       if (result < 0) {
+                               dprintk(DEBUG_ERROR, "clone error: %s\n",
+                                       FCALL_ERROR(fcall));
+                               kfree(fcall);
+                               return result;
+                       }
+
+                       v9newfid = v9fs_fid_create(file->f_dentry);
+                       v9newfid->fid = newfid;
+                       v9newfid->qid = v9fid->qid;
+                       v9newfid->iounit = v9fid->iounit;
+                       v9newfid->fidopen = 0;
+                       v9newfid->fidclunked = 0;
+                       v9newfid->v9ses = v9ses;
+                       v9fid = v9newfid;
+                       kfree(fcall);
+               }
+
+               /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
+               /* translate open mode appropriately */
+               open_mode = file->f_flags & 0x3;
+
+               if (file->f_flags & O_EXCL)
+                       open_mode |= V9FS_OEXCL;
+
+               if (v9ses->extended) {
+                       if (file->f_flags & O_TRUNC)
+                               open_mode |= V9FS_OTRUNC;
+
+                       if (file->f_flags & O_APPEND)
+                               open_mode |= V9FS_OAPPEND;
+               }
+
+               result = v9fs_t_open(v9ses, newfid, open_mode, &fcall);
+               if (result < 0) {
+                       dprintk(DEBUG_ERROR,
+                               "open failed, open_mode 0x%x: %s\n", open_mode,
+                               FCALL_ERROR(fcall));
+                       kfree(fcall);
+                       return result;
+               }
+
+               iounit = fcall->params.ropen.iounit;
+               kfree(fcall);
+       }
+
+
+       file->private_data = v9fid;
+
+       v9fid->rdir_pos = 0;
+       v9fid->rdir_fcall = NULL;
+       v9fid->fidopen = 1;
+       v9fid->filp = file;
+       v9fid->iounit = iounit;
+
+       return 0;
+}
+
+/**
+ * v9fs_file_lock - lock a file (or directory)
+ * @inode: inode to be opened
+ * @file: file being opened
+ *
+ * XXX - this looks like a local only lock, we should extend into 9P
+ *       by using open exclusive
+ */
+
+static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
+{
+       int res = 0;
+       struct inode *inode = filp->f_dentry->d_inode;
+
+       dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
+
+       /* No mandatory locks */
+       if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+               return -ENOLCK;
+
+       if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
+               filemap_fdatawrite(inode->i_mapping);
+               filemap_fdatawait(inode->i_mapping);
+               invalidate_inode_pages(&inode->i_data);
+       }
+
+       return res;
+}
+
+/**
+ * v9fs_read - read from a file (internal)
+ * @filep: file pointer to read
+ * @data: data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+
+static ssize_t
+v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+       struct v9fs_fid *v9f = filp->private_data;
+       struct v9fs_fcall *fcall = NULL;
+       int fid = v9f->fid;
+       int rsize = 0;
+       int result = 0;
+       int total = 0;
+
+       dprintk(DEBUG_VFS, "\n");
+
+       rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+       if (v9f->iounit != 0 && rsize > v9f->iounit)
+               rsize = v9f->iounit;
+
+       do {
+               if (count < rsize)
+                       rsize = count;
+
+               result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall);
+
+               if (result < 0) {
+                       printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n",
+                              result);
+
+                       kfree(fcall);
+                       return total;
+               } else
+                       *offset += result;
+
+               /* XXX - extra copy */
+               memcpy(buffer, fcall->params.rread.data, result);
+               count -= result;
+               buffer += result;
+               total += result;
+
+               kfree(fcall);
+
+               if (result < rsize)
+                       break;
+       } while (count);
+
+       return total;
+}
+
+/**
+ * v9fs_file_read - read from a file
+ * @filep: file pointer to read
+ * @data: data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+
+static ssize_t
+v9fs_file_read(struct file *filp, char __user * data, size_t count,
+              loff_t * offset)
+{
+       int retval = -1;
+       int ret = 0;
+       char *buffer;
+
+       buffer = kmalloc(count, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       retval = v9fs_read(filp, buffer, count, offset);
+       if (retval > 0) {
+               if ((ret = copy_to_user(data, buffer, retval)) != 0) {
+                       dprintk(DEBUG_ERROR, "Problem copying to user %d\n",
+                               ret);
+                       retval = ret;
+               }
+       }
+
+       kfree(buffer);
+
+       return retval;
+}
+
+/**
+ * v9fs_write - write to a file
+ * @filep: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+
+static ssize_t
+v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+       struct v9fs_fid *v9fid = filp->private_data;
+       struct v9fs_fcall *fcall;
+       int fid = v9fid->fid;
+       int result = -EIO;
+       int rsize = 0;
+       int total = 0;
+
+       dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count,
+               (int)*offset);
+       rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+       if (v9fid->iounit != 0 && rsize > v9fid->iounit)
+               rsize = v9fid->iounit;
+
+       dump_data(buffer, count);
+
+       do {
+               if (count < rsize)
+                       rsize = count;
+
+               result =
+                   v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall);
+               if (result < 0) {
+                       eprintk(KERN_ERR, "error while writing: %s(%d)\n",
+                               FCALL_ERROR(fcall), result);
+                       kfree(fcall);
+                       return result;
+               } else
+                       *offset += result;
+
+               kfree(fcall);
+
+               if (result != rsize) {
+                       eprintk(KERN_ERR,
+                               "short write: v9fs_t_write returned %d\n",
+                               result);
+                       break;
+               }
+
+               count -= result;
+               buffer += result;
+               total += result;
+       } while (count);
+
+       return total;
+}
+
+/**
+ * v9fs_file_write - write to a file
+ * @filep: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+
+static ssize_t
+v9fs_file_write(struct file *filp, const char __user * data,
+               size_t count, loff_t * offset)
+{
+       int ret = -1;
+       char *buffer;
+
+       buffer = kmalloc(count, GFP_KERNEL);
+       if (buffer == NULL)
+               return -ENOMEM;
+
+       ret = copy_from_user(buffer, data, count);
+       if (ret) {
+               dprintk(DEBUG_ERROR, "Problem copying from user\n");
+               ret = -EFAULT;
+       } else {
+               ret = v9fs_write(filp, buffer, count, offset);
+       }
+
+       kfree(buffer);
+
+       return ret;
+}
+
+struct file_operations v9fs_file_operations = {
+       .llseek = generic_file_llseek,
+       .read = v9fs_file_read,
+       .write = v9fs_file_write,
+       .open = v9fs_file_open,
+       .release = v9fs_dir_release,
+       .lock = v9fs_file_lock,
+};
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
new file mode 100644 (file)
index 0000000..0c13fc6
--- /dev/null
@@ -0,0 +1,1338 @@
+/*
+ *  linux/fs/9p/vfs_inode.c
+ *
+ * This file contains vfs inode ops for the 9P2000 protocol.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/namei.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+static struct inode_operations v9fs_dir_inode_operations;
+static struct inode_operations v9fs_dir_inode_operations_ext;
+static struct inode_operations v9fs_file_inode_operations;
+static struct inode_operations v9fs_symlink_inode_operations;
+
+/**
+ * unixmode2p9mode - convert unix mode bits to plan 9
+ * @v9ses: v9fs session information
+ * @mode: mode to convert
+ *
+ */
+
+static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
+{
+       int res;
+       res = mode & 0777;
+       if (S_ISDIR(mode))
+               res |= V9FS_DMDIR;
+       if (v9ses->extended) {
+               if (S_ISLNK(mode))
+                       res |= V9FS_DMSYMLINK;
+               if (v9ses->nodev == 0) {
+                       if (S_ISSOCK(mode))
+                               res |= V9FS_DMSOCKET;
+                       if (S_ISFIFO(mode))
+                               res |= V9FS_DMNAMEDPIPE;
+                       if (S_ISBLK(mode))
+                               res |= V9FS_DMDEVICE;
+                       if (S_ISCHR(mode))
+                               res |= V9FS_DMDEVICE;
+               }
+
+               if ((mode & S_ISUID) == S_ISUID)
+                       res |= V9FS_DMSETUID;
+               if ((mode & S_ISGID) == S_ISGID)
+                       res |= V9FS_DMSETGID;
+               if ((mode & V9FS_DMLINK))
+                       res |= V9FS_DMLINK;
+       }
+
+       return res;
+}
+
+/**
+ * p9mode2unixmode- convert plan9 mode bits to unix mode bits
+ * @v9ses: v9fs session information
+ * @mode: mode to convert
+ *
+ */
+
+static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
+{
+       int res;
+
+       res = mode & 0777;
+
+       if ((mode & V9FS_DMDIR) == V9FS_DMDIR)
+               res |= S_IFDIR;
+       else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended))
+               res |= S_IFLNK;
+       else if ((mode & V9FS_DMSOCKET) && (v9ses->extended)
+                && (v9ses->nodev == 0))
+               res |= S_IFSOCK;
+       else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended)
+                && (v9ses->nodev == 0))
+               res |= S_IFIFO;
+       else if ((mode & V9FS_DMDEVICE) && (v9ses->extended)
+                && (v9ses->nodev == 0))
+               res |= S_IFBLK;
+       else
+               res |= S_IFREG;
+
+       if (v9ses->extended) {
+               if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID)
+                       res |= S_ISUID;
+
+               if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID)
+                       res |= S_ISGID;
+       }
+
+       return res;
+}
+
+/**
+ * v9fs_blank_mistat - helper function to setup a 9P stat structure
+ * @v9ses: 9P session info (for determining extended mode)
+ * @mistat: structure to initialize
+ *
+ */
+
+static void
+v9fs_blank_mistat(struct v9fs_session_info *v9ses, struct v9fs_stat *mistat)
+{
+       mistat->type = ~0;
+       mistat->dev = ~0;
+       mistat->qid.type = ~0;
+       mistat->qid.version = ~0;
+       *((long long *)&mistat->qid.path) = ~0;
+       mistat->mode = ~0;
+       mistat->atime = ~0;
+       mistat->mtime = ~0;
+       mistat->length = ~0;
+       mistat->name = mistat->data;
+       mistat->uid = mistat->data;
+       mistat->gid = mistat->data;
+       mistat->muid = mistat->data;
+       if (v9ses->extended) {
+               mistat->n_uid = ~0;
+               mistat->n_gid = ~0;
+               mistat->n_muid = ~0;
+               mistat->extension = mistat->data;
+       }
+       *mistat->data = 0;
+}
+
+/**
+ * v9fs_mistat2unix - convert mistat to unix stat
+ * @mistat: Plan 9 metadata (mistat) structure
+ * @buf: unix metadata (stat) structure to populate
+ * @sb: superblock
+ *
+ */
+
+static void
+v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf,
+                struct super_block *sb)
+{
+       struct v9fs_session_info *v9ses = sb ? sb->s_fs_info : NULL;
+
+       buf->st_nlink = 1;
+
+       buf->st_atime = mistat->atime;
+       buf->st_mtime = mistat->mtime;
+       buf->st_ctime = mistat->mtime;
+
+       buf->st_uid = (unsigned short)-1;
+       buf->st_gid = (unsigned short)-1;
+
+       if (v9ses && v9ses->extended) {
+               /* TODO: string to uid mapping via user-space daemon */
+               if (mistat->n_uid != -1)
+                       sscanf(mistat->uid, "%x", (unsigned int *)&buf->st_uid);
+
+               if (mistat->n_gid != -1)
+                       sscanf(mistat->gid, "%x", (unsigned int *)&buf->st_gid);
+       }
+
+       if (buf->st_uid == (unsigned short)-1)
+               buf->st_uid = v9ses->uid;
+       if (buf->st_gid == (unsigned short)-1)
+               buf->st_gid = v9ses->gid;
+
+       buf->st_mode = p9mode2unixmode(v9ses, mistat->mode);
+       if ((S_ISBLK(buf->st_mode)) || (S_ISCHR(buf->st_mode))) {
+               char type = 0;
+               int major = -1;
+               int minor = -1;
+               sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
+               switch (type) {
+               case 'c':
+                       buf->st_mode &= ~S_IFBLK;
+                       buf->st_mode |= S_IFCHR;
+                       break;
+               case 'b':
+                       break;
+               default:
+                       dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
+                               type, mistat->extension);
+               };
+               buf->st_rdev = MKDEV(major, minor);
+       } else
+               buf->st_rdev = 0;
+
+       buf->st_size = mistat->length;
+
+       buf->st_blksize = sb->s_blocksize;
+       buf->st_blocks =
+           (buf->st_size + buf->st_blksize - 1) >> sb->s_blocksize_bits;
+}
+
+/**
+ * v9fs_get_inode - helper function to setup an inode
+ * @sb: superblock
+ * @mode: mode to setup inode with
+ *
+ */
+
+struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+{
+       struct inode *inode = NULL;
+       struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+       dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+
+       inode = new_inode(sb);
+       if (inode) {
+               inode->i_mode = mode;
+               inode->i_uid = current->fsuid;
+               inode->i_gid = current->fsgid;
+               inode->i_blksize = sb->s_blocksize;
+               inode->i_blocks = 0;
+               inode->i_rdev = 0;
+               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+               switch (mode & S_IFMT) {
+               case S_IFIFO:
+               case S_IFBLK:
+               case S_IFCHR:
+               case S_IFSOCK:
+                       if(!v9ses->extended) {
+                               dprintk(DEBUG_ERROR, "special files without extended mode\n");
+                               return ERR_PTR(-EINVAL);
+                       }
+                       init_special_inode(inode, inode->i_mode,
+                                          inode->i_rdev);
+                       break;
+               case S_IFREG:
+                       inode->i_op = &v9fs_file_inode_operations;
+                       inode->i_fop = &v9fs_file_operations;
+                       break;
+               case S_IFLNK:
+                       if(!v9ses->extended) {
+                               dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n");
+                               return ERR_PTR(-EINVAL);
+                       }
+                       inode->i_op = &v9fs_symlink_inode_operations;
+                       break;
+               case S_IFDIR:
+                       inode->i_nlink++;
+                       if(v9ses->extended)
+                               inode->i_op = &v9fs_dir_inode_operations_ext;
+                       else
+                               inode->i_op = &v9fs_dir_inode_operations;
+                       inode->i_fop = &v9fs_dir_operations;
+                       break;
+               default:
+                       dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+                               mode, mode & S_IFMT);
+                       return ERR_PTR(-EINVAL);
+               }
+       } else {
+               eprintk(KERN_WARNING, "Problem allocating inode\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       return inode;
+}
+
+/**
+ * v9fs_create - helper function to create files and directories
+ * @dir: directory inode file is being created in
+ * @file_dentry: dentry file is being created in
+ * @perm: permissions file is being created with
+ * @open_mode: resulting open mode for file
+ *
+ */
+
+static int
+v9fs_create(struct inode *dir,
+           struct dentry *file_dentry,
+           unsigned int perm, unsigned int open_mode)
+{
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       struct super_block *sb = dir->i_sb;
+       struct v9fs_fid *dirfid =
+           v9fs_fid_lookup(file_dentry->d_parent, FID_WALK);
+       struct v9fs_fid *fid = NULL;
+       struct inode *file_inode = NULL;
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_qid qid;
+       struct stat newstat;
+       int dirfidnum = -1;
+       long newfid = -1;
+       int result = 0;
+       unsigned int iounit = 0;
+
+       perm = unixmode2p9mode(v9ses, perm);
+
+       dprintk(DEBUG_VFS, "dir: %p dentry: %p perm: %o mode: %o\n", dir,
+               file_dentry, perm, open_mode);
+
+       if (!dirfid)
+               return -EBADF;
+
+       dirfidnum = dirfid->fid;
+       if (dirfidnum < 0) {
+               dprintk(DEBUG_ERROR, "No fid for the directory #%lu\n",
+                       dir->i_ino);
+               return -EBADF;
+       }
+
+       if (file_dentry->d_inode) {
+               dprintk(DEBUG_ERROR,
+                       "Odd. There is an inode for dir %lu, name :%s:\n",
+                       dir->i_ino, file_dentry->d_name.name);
+               return -EEXIST;
+       }
+
+       newfid = v9fs_get_idpool(&v9ses->fidpool);
+       if (newfid < 0) {
+               eprintk(KERN_WARNING, "no free fids available\n");
+               return -ENOSPC;
+       }
+
+       result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall);
+       if (result < 0) {
+               dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
+               v9fs_put_idpool(newfid, &v9ses->fidpool);
+               newfid = 0;
+               goto CleanUpFid;
+       }
+
+       kfree(fcall);
+
+       result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name,
+                              perm, open_mode, &fcall);
+       if (result < 0) {
+               dprintk(DEBUG_ERROR, "create fails: %s(%d)\n",
+                       FCALL_ERROR(fcall), result);
+
+               goto CleanUpFid;
+       }
+
+       iounit = fcall->params.rcreate.iounit;
+       qid = fcall->params.rcreate.qid;
+       kfree(fcall);
+
+       fid = v9fs_fid_create(file_dentry);
+       if (!fid) {
+               result = -ENOMEM;
+               goto CleanUpFid;
+       }
+
+       fid->fid = newfid;
+       fid->fidopen = 0;
+       fid->fidcreate = 1;
+       fid->qid = qid;
+       fid->iounit = iounit;
+       fid->rdir_pos = 0;
+       fid->rdir_fcall = NULL;
+       fid->v9ses = v9ses;
+
+       if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) ||
+           (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) ||
+           (perm & V9FS_DMDEVICE))
+               return 0;
+
+       result = v9fs_t_stat(v9ses, newfid, &fcall);
+       if (result < 0) {
+               dprintk(DEBUG_ERROR, "stat error: %s(%d)\n", FCALL_ERROR(fcall),
+                       result);
+               goto CleanUpFid;
+       }
+
+       v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
+
+       file_inode = v9fs_get_inode(sb, newstat.st_mode);
+       if ((!file_inode) || IS_ERR(file_inode)) {
+               dprintk(DEBUG_ERROR, "create inode failed\n");
+               result = -EBADF;
+               goto CleanUpFid;
+       }
+
+       v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb);
+       kfree(fcall);
+       d_instantiate(file_dentry, file_inode);
+
+       if (perm & V9FS_DMDIR) {
+               if (v9fs_t_clunk(v9ses, newfid, &fcall))
+                       dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n",
+                               FCALL_ERROR(fcall));
+
+               v9fs_put_idpool(newfid, &v9ses->fidpool);
+               kfree(fcall);
+               fid->fidopen = 0;
+               fid->fidcreate = 0;
+               d_drop(file_dentry);
+       }
+
+       return 0;
+
+      CleanUpFid:
+       kfree(fcall);
+
+       if (newfid) {
+               if (v9fs_t_clunk(v9ses, newfid, &fcall))
+                       dprintk(DEBUG_ERROR, "clunk failed: %s\n",
+                               FCALL_ERROR(fcall));
+
+               v9fs_put_idpool(newfid, &v9ses->fidpool);
+               kfree(fcall);
+       }
+       return result;
+}
+
+/**
+ * v9fs_remove - helper function to remove files and directories
+ * @dir: directory inode that is being deleted
+ * @file:  dentry that is being deleted
+ * @rmdir: removing a directory
+ *
+ */
+
+static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
+{
+       struct v9fs_fcall *fcall = NULL;
+       struct super_block *sb = NULL;
+       struct v9fs_session_info *v9ses = NULL;
+       struct v9fs_fid *v9fid = NULL;
+       struct inode *file_inode = NULL;
+       int fid = -1;
+       int result = 0;
+
+       dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
+               rmdir);
+
+       file_inode = file->d_inode;
+       sb = file_inode->i_sb;
+       v9ses = v9fs_inode2v9ses(file_inode);
+       v9fid = v9fs_fid_lookup(file, FID_OP);
+
+       if (!v9fid) {
+               dprintk(DEBUG_ERROR,
+                       "no v9fs_fid\n");
+               return -EBADF;
+       }
+
+       fid = v9fid->fid;
+       if (fid < 0) {
+               dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n",
+                       file_inode->i_ino);
+               return -EBADF;
+       }
+
+       result = v9fs_t_remove(v9ses, fid, &fcall);
+       if (result < 0)
+               dprintk(DEBUG_ERROR, "remove of file fails: %s(%d)\n",
+                       FCALL_ERROR(fcall), result);
+       else {
+               v9fs_put_idpool(fid, &v9ses->fidpool);
+               v9fs_fid_destroy(v9fid);
+       }
+
+       kfree(fcall);
+       return result;
+}
+
+/**
+ * v9fs_vfs_create - VFS hook to create files
+ * @inode: directory inode that is being deleted
+ * @dentry:  dentry that is being deleted
+ * @perm: create permissions
+ * @nd: path information
+ *
+ */
+
+static int
+v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm,
+               struct nameidata *nd)
+{
+       return v9fs_create(inode, dentry, perm, O_RDWR);
+}
+
+/**
+ * v9fs_vfs_mkdir - VFS mkdir hook to create a directory
+ * @inode:  inode that is being unlinked
+ * @dentry: dentry that is being unlinked
+ * @mode: mode for new directory
+ *
+ */
+
+static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode)
+{
+       return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY);
+}
+
+/**
+ * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode
+ * @dir:  inode that is being walked from
+ * @dentry: dentry that is being walked to?
+ * @nameidata: path data
+ *
+ */
+
+static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
+                                     struct nameidata *nameidata)
+{
+       struct super_block *sb;
+       struct v9fs_session_info *v9ses;
+       struct v9fs_fid *dirfid;
+       struct v9fs_fid *fid;
+       struct inode *inode;
+       struct v9fs_fcall *fcall = NULL;
+       struct stat newstat;
+       int dirfidnum = -1;
+       int newfid = -1;
+       int result = 0;
+
+       dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
+               dir, dentry->d_iname, dentry, nameidata);
+
+       sb = dir->i_sb;
+       v9ses = v9fs_inode2v9ses(dir);
+       dirfid = v9fs_fid_lookup(dentry->d_parent, FID_WALK);
+
+       if (!dirfid) {
+               dprintk(DEBUG_ERROR, "no dirfid\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       dirfidnum = dirfid->fid;
+
+       if (dirfidnum < 0) {
+               dprintk(DEBUG_ERROR, "no dirfid for inode %p, #%lu\n",
+                       dir, dir->i_ino);
+               return ERR_PTR(-EBADF);
+       }
+
+       newfid = v9fs_get_idpool(&v9ses->fidpool);
+       if (newfid < 0) {
+               eprintk(KERN_WARNING, "newfid fails!\n");
+               return ERR_PTR(-ENOSPC);
+       }
+
+       result =
+           v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name,
+                       NULL);
+       if (result < 0) {
+               v9fs_put_idpool(newfid, &v9ses->fidpool);
+               if (result == -ENOENT) {
+                       d_add(dentry, NULL);
+                       dprintk(DEBUG_ERROR,
+                               "Return negative dentry %p count %d\n",
+                               dentry, atomic_read(&dentry->d_count));
+                       return NULL;
+               }
+               dprintk(DEBUG_ERROR, "walk error:%d\n", result);
+               goto FreeFcall;
+       }
+
+       result = v9fs_t_stat(v9ses, newfid, &fcall);
+       if (result < 0) {
+               dprintk(DEBUG_ERROR, "stat error\n");
+               goto FreeFcall;
+       }
+
+       v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
+       inode = v9fs_get_inode(sb, newstat.st_mode);
+
+       if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
+               eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
+                       PTR_ERR(inode));
+
+               result = -ENOSPC;
+               goto FreeFcall;
+       }
+
+       inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid);
+
+       fid = v9fs_fid_create(dentry);
+       if (fid == NULL) {
+               dprintk(DEBUG_ERROR, "couldn't insert\n");
+               result = -ENOMEM;
+               goto FreeFcall;
+       }
+
+       fid->fid = newfid;
+       fid->fidopen = 0;
+       fid->v9ses = v9ses;
+       fid->qid = fcall->params.rstat.stat->qid;
+
+       dentry->d_op = &v9fs_dentry_operations;
+       v9fs_mistat2inode(fcall->params.rstat.stat, inode, inode->i_sb);
+
+       d_add(dentry, inode);
+       kfree(fcall);
+
+       return NULL;
+
+      FreeFcall:
+       kfree(fcall);
+       return ERR_PTR(result);
+}
+
+/**
+ * v9fs_vfs_unlink - VFS unlink hook to delete an inode
+ * @i:  inode that is being unlinked
+ * @d: dentry that is being unlinked
+ *
+ */
+
+static int v9fs_vfs_unlink(struct inode *i, struct dentry *d)
+{
+       return v9fs_remove(i, d, 0);
+}
+
+/**
+ * v9fs_vfs_rmdir - VFS unlink hook to delete a directory
+ * @i:  inode that is being unlinked
+ * @d: dentry that is being unlinked
+ *
+ */
+
+static int v9fs_vfs_rmdir(struct inode *i, struct dentry *d)
+{
+       return v9fs_remove(i, d, 1);
+}
+
+/**
+ * v9fs_vfs_rename - VFS hook to rename an inode
+ * @old_dir:  old dir inode
+ * @old_dentry: old dentry
+ * @new_dir: new dir inode
+ * @new_dentry: new dentry
+ *
+ */
+
+static int
+v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+               struct inode *new_dir, struct dentry *new_dentry)
+{
+       struct inode *old_inode = old_dentry->d_inode;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
+       struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_WALK);
+       struct v9fs_fid *olddirfid =
+           v9fs_fid_lookup(old_dentry->d_parent, FID_WALK);
+       struct v9fs_fid *newdirfid =
+           v9fs_fid_lookup(new_dentry->d_parent, FID_WALK);
+       struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+       struct v9fs_fcall *fcall = NULL;
+       int fid = -1;
+       int olddirfidnum = -1;
+       int newdirfidnum = -1;
+       int retval = 0;
+
+       dprintk(DEBUG_VFS, "\n");
+
+       if (!mistat)
+               return -ENOMEM;
+
+       if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
+               dprintk(DEBUG_ERROR, "problem with arguments\n");
+               return -EBADF;
+       }
+
+       /* 9P can only handle file rename in the same directory */
+       if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
+               dprintk(DEBUG_ERROR, "old dir and new dir are different\n");
+               retval = -EPERM;
+               goto FreeFcallnBail;
+       }
+
+       fid = oldfid->fid;
+       olddirfidnum = olddirfid->fid;
+       newdirfidnum = newdirfid->fid;
+
+       if (fid < 0) {
+               dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
+                       old_inode->i_ino);
+               retval = -EBADF;
+               goto FreeFcallnBail;
+       }
+
+       v9fs_blank_mistat(v9ses, mistat);
+
+       strcpy(mistat->data + 1, v9ses->name);
+       mistat->name = mistat->data + 1 + strlen(v9ses->name);
+
+       if (new_dentry->d_name.len >
+           (v9ses->maxdata - strlen(v9ses->name) - sizeof(struct v9fs_stat))) {
+               dprintk(DEBUG_ERROR, "new name too long\n");
+               goto FreeFcallnBail;
+       }
+
+       strcpy(mistat->name, new_dentry->d_name.name);
+       retval = v9fs_t_wstat(v9ses, fid, mistat, &fcall);
+
+      FreeFcallnBail:
+       kfree(mistat);
+
+       if (retval < 0)
+               dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+                       FCALL_ERROR(fcall));
+
+       kfree(fcall);
+       return retval;
+}
+
+/**
+ * v9fs_vfs_getattr - retreive file metadata
+ * @mnt - mount information
+ * @dentry - file to get attributes on
+ * @stat - metadata structure to populate
+ *
+ */
+
+static int
+v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                struct kstat *stat)
+{
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+       struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+       int err = -EPERM;
+
+       dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
+       if (!fid) {
+               dprintk(DEBUG_ERROR,
+                       "couldn't find fid associated with dentry\n");
+               return -EBADF;
+       }
+
+       err = v9fs_t_stat(v9ses, fid->fid, &fcall);
+
+       if (err < 0)
+               dprintk(DEBUG_ERROR, "stat error\n");
+       else {
+               v9fs_mistat2inode(fcall->params.rstat.stat, dentry->d_inode,
+                                 dentry->d_inode->i_sb);
+               generic_fillattr(dentry->d_inode, stat);
+       }
+
+       kfree(fcall);
+       return err;
+}
+
+/**
+ * v9fs_vfs_setattr - set file metadata
+ * @dentry: file whose metadata to set
+ * @iattr: metadata assignment structure
+ *
+ */
+
+static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+       struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+       int res = -EPERM;
+
+       dprintk(DEBUG_VFS, "\n");
+
+       if (!mistat)
+               return -ENOMEM;
+
+       if (!fid) {
+               dprintk(DEBUG_ERROR,
+                       "Couldn't find fid associated with dentry\n");
+               return -EBADF;
+       }
+
+       v9fs_blank_mistat(v9ses, mistat);
+       if (iattr->ia_valid & ATTR_MODE)
+               mistat->mode = unixmode2p9mode(v9ses, iattr->ia_mode);
+
+       if (iattr->ia_valid & ATTR_MTIME)
+               mistat->mtime = iattr->ia_mtime.tv_sec;
+
+       if (iattr->ia_valid & ATTR_ATIME)
+               mistat->atime = iattr->ia_atime.tv_sec;
+
+       if (iattr->ia_valid & ATTR_SIZE)
+               mistat->length = iattr->ia_size;
+
+       if (v9ses->extended) {
+               char *ptr = mistat->data+1;
+
+               if (iattr->ia_valid & ATTR_UID) {
+                       mistat->uid = ptr;
+                       ptr += 1+sprintf(ptr, "%08x", iattr->ia_uid);
+                       mistat->n_uid = iattr->ia_uid;
+               }
+
+               if (iattr->ia_valid & ATTR_GID) {
+                       mistat->gid = ptr;
+                       ptr += 1+sprintf(ptr, "%08x", iattr->ia_gid);
+                       mistat->n_gid = iattr->ia_gid;
+               }
+       }
+
+       res = v9fs_t_wstat(v9ses, fid->fid, mistat, &fcall);
+
+       if (res < 0)
+               dprintk(DEBUG_ERROR, "wstat error: %s\n", FCALL_ERROR(fcall));
+
+       kfree(mistat);
+       kfree(fcall);
+
+       if (res >= 0)
+               res = inode_setattr(dentry->d_inode, iattr);
+
+       return res;
+}
+
+/**
+ * v9fs_mistat2inode - populate an inode structure with mistat info
+ * @mistat: Plan 9 metadata (mistat) structure
+ * @inode: inode to populate
+ * @sb: superblock of filesystem
+ *
+ */
+
+void
+v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode,
+                 struct super_block *sb)
+{
+       struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+       inode->i_nlink = 1;
+
+       inode->i_atime.tv_sec = mistat->atime;
+       inode->i_mtime.tv_sec = mistat->mtime;
+       inode->i_ctime.tv_sec = mistat->mtime;
+
+       inode->i_uid = -1;
+       inode->i_gid = -1;
+
+       if (v9ses->extended) {
+               /* TODO: string to uid mapping via user-space daemon */
+               inode->i_uid = mistat->n_uid;
+               inode->i_gid = mistat->n_gid;
+
+               if (mistat->n_uid == -1)
+                       sscanf(mistat->uid, "%x", &inode->i_uid);
+
+               if (mistat->n_gid == -1)
+                       sscanf(mistat->gid, "%x", &inode->i_gid);
+       }
+
+       if (inode->i_uid == -1)
+               inode->i_uid = v9ses->uid;
+       if (inode->i_gid == -1)
+               inode->i_gid = v9ses->gid;
+
+       inode->i_mode = p9mode2unixmode(v9ses, mistat->mode);
+       if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
+               char type = 0;
+               int major = -1;
+               int minor = -1;
+               sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
+               switch (type) {
+               case 'c':
+                       inode->i_mode &= ~S_IFBLK;
+                       inode->i_mode |= S_IFCHR;
+                       break;
+               case 'b':
+                       break;
+               default:
+                       dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
+                               type, mistat->extension);
+               };
+               inode->i_rdev = MKDEV(major, minor);
+       } else
+               inode->i_rdev = 0;
+
+       inode->i_size = mistat->length;
+
+       inode->i_blksize = sb->s_blocksize;
+       inode->i_blocks =
+           (inode->i_size + inode->i_blksize - 1) >> sb->s_blocksize_bits;
+}
+
+/**
+ * v9fs_qid2ino - convert qid into inode number
+ * @qid: qid to hash
+ *
+ * BUG: potential for inode number collisions?
+ */
+
+ino_t v9fs_qid2ino(struct v9fs_qid *qid)
+{
+       u64 path = qid->path + 2;
+       ino_t i = 0;
+
+       if (sizeof(ino_t) == sizeof(path))
+               memcpy(&i, &path, sizeof(ino_t));
+       else
+               i = (ino_t) (path ^ (path >> 32));
+
+       return i;
+}
+
+/**
+ * v9fs_vfs_symlink - helper function to create symlinks
+ * @dir: directory inode containing symlink
+ * @dentry: dentry for symlink
+ * @symname: symlink data
+ *
+ * See 9P2000.u RFC for more information
+ *
+ */
+
+static int
+v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+{
+       int retval = -EPERM;
+       struct v9fs_fid *newfid;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+
+       dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+               symname);
+
+       if (!mistat)
+               return -ENOMEM;
+
+       if (!v9ses->extended) {
+               dprintk(DEBUG_ERROR, "not extended\n");
+               goto FreeFcall;
+       }
+
+       /* issue a create */
+       retval = v9fs_create(dir, dentry, S_IFLNK, 0);
+       if (retval != 0)
+               goto FreeFcall;
+
+       newfid = v9fs_fid_lookup(dentry, FID_OP);
+
+       /* issue a twstat */
+       v9fs_blank_mistat(v9ses, mistat);
+       strcpy(mistat->data + 1, symname);
+       mistat->extension = mistat->data + 1;
+       retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
+       if (retval < 0) {
+               dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+                       FCALL_ERROR(fcall));
+               goto FreeFcall;
+       }
+
+       kfree(fcall);
+
+       if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
+               dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
+                       FCALL_ERROR(fcall));
+               goto FreeFcall;
+       }
+
+       d_drop(dentry);         /* FID - will this also clunk? */
+
+      FreeFcall:
+       kfree(mistat);
+       kfree(fcall);
+
+       return retval;
+}
+
+/**
+ * v9fs_readlink - read a symlink's location (internal version)
+ * @dentry: dentry for symlink
+ * @buffer: buffer to load symlink location into
+ * @buflen: length of buffer
+ *
+ */
+
+static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+       int retval = -EPERM;
+
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+       struct v9fs_fid *fid = v9fs_fid_lookup(dentry, FID_OP);
+
+       if (!fid) {
+               dprintk(DEBUG_ERROR, "could not resolve fid from dentry\n");
+               retval = -EBADF;
+               goto FreeFcall;
+       }
+
+       if (!v9ses->extended) {
+               retval = -EBADF;
+               dprintk(DEBUG_ERROR, "not extended\n");
+               goto FreeFcall;
+       }
+
+       dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
+       retval = v9fs_t_stat(v9ses, fid->fid, &fcall);
+
+       if (retval < 0) {
+               dprintk(DEBUG_ERROR, "stat error\n");
+               goto FreeFcall;
+       }
+
+       if (!fcall)
+               return -EIO;
+
+       if (!(fcall->params.rstat.stat->mode & V9FS_DMSYMLINK)) {
+               retval = -EINVAL;
+               goto FreeFcall;
+       }
+
+       /* copy extension buffer into buffer */
+       if (strlen(fcall->params.rstat.stat->extension) < buflen)
+               buflen = strlen(fcall->params.rstat.stat->extension);
+
+       memcpy(buffer, fcall->params.rstat.stat->extension, buflen + 1);
+
+       retval = buflen;
+
+      FreeFcall:
+       kfree(fcall);
+
+       return retval;
+}
+
+/**
+ * v9fs_vfs_readlink - read a symlink's location
+ * @dentry: dentry for symlink
+ * @buf: buffer to load symlink location into
+ * @buflen: length of buffer
+ *
+ */
+
+static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
+                            int buflen)
+{
+       int retval;
+       int ret;
+       char *link = __getname();
+
+       if (strlen(link) < buflen)
+               buflen = strlen(link);
+
+       dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+
+       retval = v9fs_readlink(dentry, link, buflen);
+
+       if (retval > 0) {
+               if ((ret = copy_to_user(buffer, link, retval)) != 0) {
+                       dprintk(DEBUG_ERROR, "problem copying to user: %d\n",
+                               ret);
+                       retval = ret;
+               }
+       }
+
+       putname(link);
+       return retval;
+}
+
+/**
+ * v9fs_vfs_follow_link - follow a symlink path
+ * @dentry: dentry for symlink
+ * @nd: nameidata
+ *
+ */
+
+static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       int len = 0;
+       char *link = __getname();
+
+       dprintk(DEBUG_VFS, "%s n", dentry->d_name.name);
+
+       if (!link)
+               link = ERR_PTR(-ENOMEM);
+       else {
+               len = v9fs_readlink(dentry, link, strlen(link));
+
+               if (len < 0) {
+                       putname(link);
+                       link = ERR_PTR(len);
+               } else
+                       link[len] = 0;
+       }
+       nd_set_link(nd, link);
+
+       return NULL;
+}
+
+/**
+ * v9fs_vfs_put_link - release a symlink path
+ * @dentry: dentry for symlink
+ * @nd: nameidata
+ *
+ */
+
+static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
+{
+       char *s = nd_get_link(nd);
+
+       dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
+       if (!IS_ERR(s))
+               putname(s);
+}
+
+/**
+ * v9fs_vfs_link - create a hardlink
+ * @old_dentry: dentry for file to link to
+ * @dir: inode destination for new link
+ * @dentry: dentry for link
+ *
+ */
+
+/* XXX - lots of code dup'd from symlink and creates,
+ * figure out a better reuse strategy
+ */
+
+static int
+v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
+             struct dentry *dentry)
+{
+       int retval = -EPERM;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+       struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry, FID_OP);
+       struct v9fs_fid *newfid = NULL;
+       char *symname = __getname();
+
+       dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+               old_dentry->d_name.name);
+
+       if (!v9ses->extended) {
+               dprintk(DEBUG_ERROR, "not extended\n");
+               goto FreeMem;
+       }
+
+       /* get fid of old_dentry */
+       sprintf(symname, "hardlink(%d)\n", oldfid->fid);
+
+       /* issue a create */
+       retval = v9fs_create(dir, dentry, V9FS_DMLINK, 0);
+       if (retval != 0)
+               goto FreeMem;
+
+       newfid = v9fs_fid_lookup(dentry, FID_OP);
+       if (!newfid) {
+               dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
+               goto FreeMem;
+       }
+
+       /* issue a twstat */
+       v9fs_blank_mistat(v9ses, mistat);
+       strcpy(mistat->data + 1, symname);
+       mistat->extension = mistat->data + 1;
+       retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
+       if (retval < 0) {
+               dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+                       FCALL_ERROR(fcall));
+               goto FreeMem;
+       }
+
+       kfree(fcall);
+
+       if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
+               dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
+                       FCALL_ERROR(fcall));
+               goto FreeMem;
+       }
+
+       d_drop(dentry);         /* FID - will this also clunk? */
+
+       kfree(fcall);
+       fcall = NULL;
+
+      FreeMem:
+       kfree(mistat);
+       kfree(fcall);
+       putname(symname);
+       return retval;
+}
+
+/**
+ * v9fs_vfs_mknod - create a special file
+ * @dir: inode destination for new link
+ * @dentry: dentry for file
+ * @mode: mode for creation
+ * @dev_t: device associated with special file
+ *
+ */
+
+static int
+v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+{
+       int retval = -EPERM;
+       struct v9fs_fid *newfid;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       struct v9fs_fcall *fcall = NULL;
+       struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+       char *symname = __getname();
+
+       dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
+               dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
+
+       if (!mistat)
+               return -ENOMEM;
+
+       if (!new_valid_dev(rdev)) {
+               retval = -EINVAL;
+               goto FreeMem;
+       }
+
+       if (!v9ses->extended) {
+               dprintk(DEBUG_ERROR, "not extended\n");
+               goto FreeMem;
+       }
+
+       /* issue a create */
+       retval = v9fs_create(dir, dentry, mode, 0);
+
+       if (retval != 0)
+               goto FreeMem;
+
+       newfid = v9fs_fid_lookup(dentry, FID_OP);
+       if (!newfid) {
+               dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n");
+               retval = -EINVAL;
+               goto FreeMem;
+       }
+
+       /* build extension */
+       if (S_ISBLK(mode))
+               sprintf(symname, "b %u %u", MAJOR(rdev), MINOR(rdev));
+       else if (S_ISCHR(mode))
+               sprintf(symname, "c %u %u", MAJOR(rdev), MINOR(rdev));
+       else if (S_ISFIFO(mode))
+               ;       /* DO NOTHING */
+       else {
+               retval = -EINVAL;
+               goto FreeMem;
+       }
+
+       if (!S_ISFIFO(mode)) {
+               /* issue a twstat */
+               v9fs_blank_mistat(v9ses, mistat);
+               strcpy(mistat->data + 1, symname);
+               mistat->extension = mistat->data + 1;
+               retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
+               if (retval < 0) {
+                       dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
+                               FCALL_ERROR(fcall));
+                       goto FreeMem;
+               }
+       }
+
+       /* need to update dcache so we show up */
+       kfree(fcall);
+
+       if (v9fs_t_clunk(v9ses, newfid->fid, &fcall)) {
+               dprintk(DEBUG_ERROR, "clunk for symlink failed: %s\n",
+                       FCALL_ERROR(fcall));
+               goto FreeMem;
+       }
+
+       d_drop(dentry);         /* FID - will this also clunk? */
+
+      FreeMem:
+       kfree(mistat);
+       kfree(fcall);
+       putname(symname);
+
+       return retval;
+}
+
+static struct inode_operations v9fs_dir_inode_operations_ext = {
+       .create = v9fs_vfs_create,
+       .lookup = v9fs_vfs_lookup,
+       .symlink = v9fs_vfs_symlink,
+       .link = v9fs_vfs_link,
+       .unlink = v9fs_vfs_unlink,
+       .mkdir = v9fs_vfs_mkdir,
+       .rmdir = v9fs_vfs_rmdir,
+       .mknod = v9fs_vfs_mknod,
+       .rename = v9fs_vfs_rename,
+       .readlink = v9fs_vfs_readlink,
+       .getattr = v9fs_vfs_getattr,
+       .setattr = v9fs_vfs_setattr,
+};
+
+static struct inode_operations v9fs_dir_inode_operations = {
+       .create = v9fs_vfs_create,
+       .lookup = v9fs_vfs_lookup,
+       .unlink = v9fs_vfs_unlink,
+       .mkdir = v9fs_vfs_mkdir,
+       .rmdir = v9fs_vfs_rmdir,
+       .mknod = v9fs_vfs_mknod,
+       .rename = v9fs_vfs_rename,
+       .getattr = v9fs_vfs_getattr,
+       .setattr = v9fs_vfs_setattr,
+};
+
+static struct inode_operations v9fs_file_inode_operations = {
+       .getattr = v9fs_vfs_getattr,
+       .setattr = v9fs_vfs_setattr,
+};
+
+static struct inode_operations v9fs_symlink_inode_operations = {
+       .readlink = v9fs_vfs_readlink,
+       .follow_link = v9fs_vfs_follow_link,
+       .put_link = v9fs_vfs_put_link,
+       .getattr = v9fs_vfs_getattr,
+       .setattr = v9fs_vfs_setattr,
+};
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
new file mode 100644 (file)
index 0000000..868f350
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *  linux/fs/9p/vfs_super.c
+ *
+ * This file contians superblock ops for 9P2000. It is intended that
+ * you mount this file system on directories.
+ *
+ *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ *  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:
+ *  Free Software Foundation
+ *  51 Franklin Street, Fifth Floor
+ *  Boston, MA  02111-1301  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/inet.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "conv.h"
+#include "fid.h"
+
+static void v9fs_clear_inode(struct inode *);
+static struct super_operations v9fs_super_ops;
+
+/**
+ * v9fs_clear_inode - release an inode
+ * @inode: inode to release
+ *
+ */
+
+static void v9fs_clear_inode(struct inode *inode)
+{
+       filemap_fdatawrite(inode->i_mapping);
+}
+
+/**
+ * v9fs_set_super - set the superblock
+ * @s: super block
+ * @data: file system specific data
+ *
+ */
+
+static int v9fs_set_super(struct super_block *s, void *data)
+{
+       s->s_fs_info = data;
+       return set_anon_super(s, data);
+}
+
+/**
+ * v9fs_fill_super - populate superblock with info
+ * @sb: superblock
+ * @v9ses: session information
+ *
+ */
+
+static void
+v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
+               int flags)
+{
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
+       sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
+       sb->s_blocksize = 1 << sb->s_blocksize_bits;
+       sb->s_magic = V9FS_MAGIC;
+       sb->s_op = &v9fs_super_ops;
+
+       sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
+           MS_NODIRATIME | MS_NOATIME;
+}
+
+/**
+ * v9fs_get_sb - mount a superblock
+ * @fs_type: file system type
+ * @flags: mount flags
+ * @dev_name: device name that was mounted
+ * @data: mount options
+ *
+ */
+
+static struct super_block *v9fs_get_sb(struct file_system_type
+                                      *fs_type, int flags,
+                                      const char *dev_name, void *data)
+{
+       struct super_block *sb = NULL;
+       struct v9fs_fcall *fcall = NULL;
+       struct inode *inode = NULL;
+       struct dentry *root = NULL;
+       struct v9fs_session_info *v9ses = NULL;
+       struct v9fs_fid *root_fid = NULL;
+       int mode = S_IRWXUGO | S_ISVTX;
+       uid_t uid = current->fsuid;
+       gid_t gid = current->fsgid;
+       int stat_result = 0;
+       int newfid = 0;
+       int retval = 0;
+
+       dprintk(DEBUG_VFS, " \n");
+
+       v9ses = kcalloc(1, sizeof(struct v9fs_session_info), GFP_KERNEL);
+       if (!v9ses)
+               return ERR_PTR(-ENOMEM);
+
+       if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
+               dprintk(DEBUG_ERROR, "problem initiating session\n");
+               retval = newfid;
+               goto free_session;
+       }
+
+       sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
+
+       v9fs_fill_super(sb, v9ses, flags);
+
+       inode = v9fs_get_inode(sb, S_IFDIR | mode);
+       if (IS_ERR(inode)) {
+               retval = PTR_ERR(inode);
+               goto put_back_sb;
+       }
+
+       inode->i_uid = uid;
+       inode->i_gid = gid;
+
+       root = d_alloc_root(inode);
+
+       if (!root) {
+               retval = -ENOMEM;
+               goto release_inode;
+       }
+
+       sb->s_root = root;
+
+       /* Setup the Root Inode */
+       root_fid = v9fs_fid_create(root);
+       if (root_fid == NULL) {
+               retval = -ENOMEM;
+               goto release_dentry;
+       }
+
+       root_fid->fidopen = 0;
+       root_fid->v9ses = v9ses;
+
+       stat_result = v9fs_t_stat(v9ses, newfid, &fcall);
+       if (stat_result < 0) {
+               dprintk(DEBUG_ERROR, "stat error\n");
+               v9fs_t_clunk(v9ses, newfid, NULL);
+               v9fs_put_idpool(newfid, &v9ses->fidpool);
+       } else {
+               root_fid->fid = newfid;
+               root_fid->qid = fcall->params.rstat.stat->qid;
+               root->d_inode->i_ino =
+                   v9fs_qid2ino(&fcall->params.rstat.stat->qid);
+               v9fs_mistat2inode(fcall->params.rstat.stat, root->d_inode, sb);
+       }
+
+       kfree(fcall);
+
+       if (stat_result < 0) {
+               retval = stat_result;
+               goto release_dentry;
+       }
+
+       return sb;
+
+      release_dentry:
+       dput(sb->s_root);
+
+      release_inode:
+       iput(inode);
+
+      put_back_sb:
+       up_write(&sb->s_umount);
+       deactivate_super(sb);
+       v9fs_session_close(v9ses);
+
+      free_session:
+       kfree(v9ses);
+
+       return ERR_PTR(retval);
+}
+
+/**
+ * v9fs_kill_super - Kill Superblock
+ * @s: superblock
+ *
+ */
+
+static void v9fs_kill_super(struct super_block *s)
+{
+       struct v9fs_session_info *v9ses = s->s_fs_info;
+
+       dprintk(DEBUG_VFS, " %p\n", s);
+
+       v9fs_dentry_release(s->s_root); /* clunk root */
+
+       kill_anon_super(s);
+
+       v9fs_session_close(v9ses);
+       kfree(v9ses);
+       dprintk(DEBUG_VFS, "exiting kill_super\n");
+}
+
+/**
+ * v9fs_show_options - Show mount options in /proc/mounts
+ * @m: seq_file to write to
+ * @mnt: mount descriptor
+ *
+ */
+
+static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+       struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
+
+       if (v9ses->debug != 0)
+               seq_printf(m, ",debug=%u", v9ses->debug);
+       if (v9ses->port != V9FS_PORT)
+               seq_printf(m, ",port=%u", v9ses->port);
+       if (v9ses->maxdata != 9000)
+               seq_printf(m, ",msize=%u", v9ses->maxdata);
+       if (v9ses->afid != ~0)
+               seq_printf(m, ",afid=%u", v9ses->afid);
+       if (v9ses->proto == PROTO_UNIX)
+               seq_puts(m, ",proto=unix");
+       if (v9ses->extended == 0)
+               seq_puts(m, ",noextend");
+       if (v9ses->nodev == 1)
+               seq_puts(m, ",nodevmap");
+       seq_printf(m, ",name=%s", v9ses->name);
+       seq_printf(m, ",aname=%s", v9ses->remotename);
+       seq_printf(m, ",uid=%u", v9ses->uid);
+       seq_printf(m, ",gid=%u", v9ses->gid);
+       return 0;
+}
+
+static void
+v9fs_umount_begin(struct super_block *sb)
+{
+       struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+       v9fs_session_cancel(v9ses);
+}
+
+static struct super_operations v9fs_super_ops = {
+       .statfs = simple_statfs,
+       .clear_inode = v9fs_clear_inode,
+       .show_options = v9fs_show_options,
+       .umount_begin = v9fs_umount_begin,
+};
+
+struct file_system_type v9fs_fs_type = {
+       .name = "9P",
+       .get_sb = v9fs_get_sb,
+       .kill_sb = v9fs_kill_super,
+       .owner = THIS_MODULE,
+};
index 5e817902cb3b408db8c02467a47b856d64eb8b09..068ccea2f184b5beadb2add2a59a86305e0487d3 100644 (file)
@@ -462,6 +462,19 @@ config AUTOFS4_FS
          local network, you probably do not need an automounter, and can say
          N here.
 
+config FUSE_FS
+       tristate "Filesystem in Userspace support"
+       help
+         With FUSE it is possible to implement a fully functional filesystem
+         in a userspace program.
+
+         There's also companion library: libfuse.  This library along with
+         utilities is available from the FUSE homepage:
+         <http://fuse.sourceforge.net/>
+
+         If you want to develop a userspace FS, or if you want to use
+         a filesystem based on FUSE, answer Y or M.
+
 menu "CD-ROM/DVD Filesystems"
 
 config ISO9660_FS
@@ -1703,6 +1716,17 @@ config AFS_FS
 config RXRPC
        tristate
 
+config 9P_FS
+       tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
+       depends on INET && EXPERIMENTAL
+       help
+         If you say Y here, you will get experimental support for
+         Plan 9 resource sharing via the 9P2000 protocol.
+
+         See <http://v9fs.sf.net> for more information.
+
+         If unsure, say N.
+
 endmenu
 
 menu "Partition Types"
index 15158309dee4ae42d2caf7429c274e20945efcbf..1972da186272906d8aa13eab878b547e44ae1398 100644 (file)
@@ -89,11 +89,13 @@ obj-$(CONFIG_QNX4FS_FS)             += qnx4/
 obj-$(CONFIG_AUTOFS_FS)                += autofs/
 obj-$(CONFIG_AUTOFS4_FS)       += autofs4/
 obj-$(CONFIG_ADFS_FS)          += adfs/
+obj-$(CONFIG_FUSE_FS)          += fuse/
 obj-$(CONFIG_UDF_FS)           += udf/
 obj-$(CONFIG_RELAYFS_FS)       += relayfs/
 obj-$(CONFIG_SUN_OPENPROMFS)   += openpromfs/
 obj-$(CONFIG_JFS_FS)           += jfs/
 obj-$(CONFIG_XFS_FS)           += xfs/
+obj-$(CONFIG_9P_FS)            += 9p/
 obj-$(CONFIG_AFS_FS)           += afs/
 obj-$(CONFIG_BEFS_FS)          += befs/
 obj-$(CONFIG_HOSTFS)           += hostfs/
index 7aa6f2004536d36a32555ac43595d9818c2331f0..9ebe881c67864d1ab04c31c0801b74d6b15b0e6d 100644 (file)
@@ -255,6 +255,7 @@ void
 affs_delete_inode(struct inode *inode)
 {
        pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
+       truncate_inode_pages(&inode->i_data, 0);
        inode->i_size = 0;
        if (S_ISREG(inode->i_mode))
                affs_truncate(inode);
index 4f641abac3c0927f2036f81f3f70106a57a09e22..38f62680fd63d70c96204c658b7a7aeedda23bd5 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -29,6 +29,7 @@
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
+#include <linux/rcuref.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
@@ -499,7 +500,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
        /* Must be done under the lock to serialise against cancellation.
         * Call this aio_fput as it duplicates fput via the fput_work.
         */
-       if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) {
+       if (unlikely(rcuref_dec_and_test(&req->ki_filp->f_count))) {
                get_ioctx(ctx);
                spin_lock(&fput_lock);
                list_add(&req->ki_list, &fput_head);
@@ -546,6 +547,24 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id)
        return ioctx;
 }
 
+static int lock_kiocb_action(void *param)
+{
+       schedule();
+       return 0;
+}
+
+static inline void lock_kiocb(struct kiocb *iocb)
+{
+       wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action,
+                        TASK_UNINTERRUPTIBLE);
+}
+
+static inline void unlock_kiocb(struct kiocb *iocb)
+{
+       kiocbClearLocked(iocb);
+       wake_up_bit(&iocb->ki_flags, KIF_LOCKED);
+}
+
 /*
  * use_mm
  *     Makes the calling kernel thread take on the specified
@@ -786,7 +805,9 @@ static int __aio_run_iocbs(struct kioctx *ctx)
                 * Hold an extra reference while retrying i/o.
                 */
                iocb->ki_users++;       /* grab extra reference */
+               lock_kiocb(iocb);
                aio_run_iocb(iocb);
+               unlock_kiocb(iocb);
                if (__aio_put_req(ctx, iocb))  /* drop extra ref */
                        put_ioctx(ctx);
        }
@@ -1527,10 +1548,9 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                goto out_put_req;
 
        spin_lock_irq(&ctx->ctx_lock);
-       if (likely(list_empty(&ctx->run_list))) {
-               aio_run_iocb(req);
-       } else {
-               list_add_tail(&req->ki_run_list, &ctx->run_list);
+       aio_run_iocb(req);
+       unlock_kiocb(req);
+       if (!list_empty(&ctx->run_list)) {
                /* drain the run list */
                while (__aio_run_iocbs(ctx))
                        ;
@@ -1661,6 +1681,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
        if (NULL != cancel) {
                struct io_event tmp;
                pr_debug("calling cancel\n");
+               lock_kiocb(kiocb);
                memset(&tmp, 0, sizeof(tmp));
                tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
                tmp.data = kiocb->ki_user_data;
@@ -1672,8 +1693,9 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
                        if (copy_to_user(result, &tmp, sizeof(tmp)))
                                ret = -EFAULT;
                }
+               unlock_kiocb(kiocb);
        } else
-               printk(KERN_DEBUG "iocb has no cancel operation\n");
+               ret = -EINVAL;
 
        put_ioctx(ctx);
 
index 6171431272dc26a08b70b0dc18d9aaa1652e8377..990c28da5aecec59a81e7fab256a3bf0cbfc7f6c 100644 (file)
@@ -105,6 +105,7 @@ struct autofs_sb_info {
        struct file *pipe;
        pid_t oz_pgrp;
        int catatonic;
+       struct super_block *sb;
        unsigned long exp_timeout;
        ino_t next_dir_ino;
        struct autofs_wait_queue *queues; /* Wait queue pointer */
@@ -134,7 +135,7 @@ void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
 void autofs_hash_delete(struct autofs_dir_ent *);
 struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *);
 void autofs_hash_dputall(struct autofs_dirhash *);
-void autofs_hash_nuke(struct autofs_dirhash *);
+void autofs_hash_nuke(struct autofs_sb_info *);
 
 /* Expiration-handling functions */
 
index 448143fd0796a36546dedb42d3ff8a38807bd5c6..5ccfcf26310d7ac6c000541300bedaae83dd267d 100644 (file)
@@ -232,13 +232,13 @@ void autofs_hash_dputall(struct autofs_dirhash *dh)
 
 /* Delete everything.  This is used on filesystem destruction, so we
    make no attempt to keep the pointers valid */
-void autofs_hash_nuke(struct autofs_dirhash *dh)
+void autofs_hash_nuke(struct autofs_sb_info *sbi)
 {
        int i;
        struct autofs_dir_ent *ent, *nent;
 
        for ( i = 0 ; i < AUTOFS_HASH_SIZE ; i++ ) {
-               for ( ent = dh->h[i] ; ent ; ent = nent ) {
+               for ( ent = sbi->dirhash.h[i] ; ent ; ent = nent ) {
                        nent = ent->next;
                        if ( ent->dentry )
                                dput(ent->dentry);
@@ -246,4 +246,5 @@ void autofs_hash_nuke(struct autofs_dirhash *dh)
                        kfree(ent);
                }
        }
+       shrink_dcache_sb(sbi->sb);
 }
index 4888c1fabbf714b32fad246d03ee7bb8db231e6a..65e5ed42190ed23f99b2aa760d0de46d56fe2b4a 100644 (file)
@@ -27,7 +27,7 @@ static void autofs_put_super(struct super_block *sb)
        if ( !sbi->catatonic )
                autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
-       autofs_hash_nuke(&sbi->dirhash);
+       autofs_hash_nuke(sbi);
        for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
                if ( test_bit(n, sbi->symlink_bitmap) )
                        kfree(sbi->symlink[n].data);
@@ -148,6 +148,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        s->s_magic = AUTOFS_SUPER_MAGIC;
        s->s_op = &autofs_sops;
        s->s_time_gran = 1;
+       sbi->sb = s;
 
        root_inode = iget(s, AUTOFS_ROOT_INO);
        root = d_alloc_root(root_inode);
index 1020dbc88bec0b5cc545b0de22d9dff4c0cd67c1..1fbc53f14aba998648c6bd3dba91590c924c4a50 100644 (file)
@@ -20,7 +20,6 @@ struct bfs_sb_info {
        unsigned long si_lasti;
        unsigned long * si_imap;
        struct buffer_head * si_sbh;            /* buffer header w/superblock */
-       struct bfs_super_block * si_bfs_sb;     /* superblock in si_sbh->b_data */
 };
 
 /*
index 5a1e5ce057ff6068472ca5fca8c4088342132588..e240c335eb231eebea5ecb9aeb73d378e22084bb 100644 (file)
@@ -2,6 +2,7 @@
  *     fs/bfs/dir.c
  *     BFS directory operations.
  *     Copyright (C) 1999,2000  Tigran Aivazian <tigran@veritas.com>
+ *      Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005
  */
 
 #include <linux/time.h>
@@ -20,9 +21,9 @@
 #define dprintf(x...)
 #endif
 
-static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino);
+static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino);
 static struct buffer_head * bfs_find_entry(struct inode * dir, 
-       const char * name, int namelen, struct bfs_dirent ** res_dir);
+       const unsigned char * name, int namelen, struct bfs_dirent ** res_dir);
 
 static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
 {
@@ -53,7 +54,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
                        de = (struct bfs_dirent *)(bh->b_data + offset);
                        if (de->ino) {
                                int size = strnlen(de->name, BFS_NAMELEN);
-                               if (filldir(dirent, de->name, size, f->f_pos, de->ino, DT_UNKNOWN) < 0) {
+                               if (filldir(dirent, de->name, size, f->f_pos, le16_to_cpu(de->ino), DT_UNKNOWN) < 0) {
                                        brelse(bh);
                                        unlock_kernel();
                                        return 0;
@@ -107,7 +108,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
        inode->i_mapping->a_ops = &bfs_aops;
        inode->i_mode = mode;
        inode->i_ino = ino;
-       BFS_I(inode)->i_dsk_ino = ino;
+       BFS_I(inode)->i_dsk_ino = cpu_to_le16(ino);
        BFS_I(inode)->i_sblock = 0;
        BFS_I(inode)->i_eblock = 0;
        insert_inode_hash(inode);
@@ -139,7 +140,7 @@ static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, st
        lock_kernel();
        bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
        if (bh) {
-               unsigned long ino = le32_to_cpu(de->ino);
+               unsigned long ino = (unsigned long)le16_to_cpu(de->ino);
                brelse(bh);
                inode = iget(dir->i_sb, ino);
                if (!inode) {
@@ -183,7 +184,7 @@ static int bfs_unlink(struct inode * dir, struct dentry * dentry)
        inode = dentry->d_inode;
        lock_kernel();
        bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
-       if (!bh || de->ino != inode->i_ino) 
+       if (!bh || le16_to_cpu(de->ino) != inode->i_ino)
                goto out_brelse;
 
        if (!inode->i_nlink) {
@@ -224,7 +225,7 @@ static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry,
                                old_dentry->d_name.name, 
                                old_dentry->d_name.len, &old_de);
 
-       if (!old_bh || old_de->ino != old_inode->i_ino)
+       if (!old_bh || le16_to_cpu(old_de->ino) != old_inode->i_ino)
                goto end_rename;
 
        error = -EPERM;
@@ -270,7 +271,7 @@ struct inode_operations bfs_dir_inops = {
        .rename                 = bfs_rename,
 };
 
-static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino)
+static int bfs_add_entry(struct inode * dir, const unsigned char * name, int namelen, int ino)
 {
        struct buffer_head * bh;
        struct bfs_dirent * de;
@@ -304,7 +305,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
                                }
                                dir->i_mtime = CURRENT_TIME_SEC;
                                mark_inode_dirty(dir);
-                               de->ino = ino;
+                               de->ino = cpu_to_le16((u16)ino);
                                for (i=0; i<BFS_NAMELEN; i++)
                                        de->name[i] = (i < namelen) ? name[i] : 0;
                                mark_buffer_dirty(bh);
@@ -317,7 +318,7 @@ static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int
        return -ENOSPC;
 }
 
-static inline int bfs_namecmp(int len, const char * name, const char * buffer)
+static inline int bfs_namecmp(int len, const unsigned char * name, const char * buffer)
 {
        if (len < BFS_NAMELEN && buffer[len])
                return 0;
@@ -325,7 +326,7 @@ static inline int bfs_namecmp(int len, const char * name, const char * buffer)
 }
 
 static struct buffer_head * bfs_find_entry(struct inode * dir, 
-       const char * name, int namelen, struct bfs_dirent ** res_dir)
+       const unsigned char * name, int namelen, struct bfs_dirent ** res_dir)
 {
        unsigned long block, offset;
        struct buffer_head * bh;
@@ -346,7 +347,7 @@ static struct buffer_head * bfs_find_entry(struct inode * dir,
                }
                de = (struct bfs_dirent *)(bh->b_data + offset);
                offset += BFS_DIRENT_SIZE;
-               if (de->ino && bfs_namecmp(namelen, name, de->name)) {
+               if (le16_to_cpu(de->ino) && bfs_namecmp(namelen, name, de->name)) {
                        *res_dir = de;
                        return bh;
                }
index 747fd1ea55e0c20e8ae2c7f7044b88af8710af87..807723b65daf3b1c93830325e441bf4b03bc81ef 100644 (file)
@@ -40,8 +40,8 @@ static int bfs_move_block(unsigned long from, unsigned long to, struct super_blo
        return 0;
 }
 
-static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned long end, 
-                               unsigned long where)
+static int bfs_move_blocks(struct super_block *sb, unsigned long start,
+                           unsigned long end, unsigned long where)
 {
        unsigned long i;
 
@@ -57,20 +57,21 @@ static int bfs_move_blocks(struct super_block *sb, unsigned long start, unsigned
 static int bfs_get_block(struct inode * inode, sector_t block, 
        struct buffer_head * bh_result, int create)
 {
-       long phys;
+       unsigned long phys;
        int err;
        struct super_block *sb = inode->i_sb;
        struct bfs_sb_info *info = BFS_SB(sb);
        struct bfs_inode_info *bi = BFS_I(inode);
        struct buffer_head *sbh = info->si_sbh;
 
-       if (block < 0 || block > info->si_blocks)
+       if (block > info->si_blocks)
                return -EIO;
 
        phys = bi->i_sblock + block;
        if (!create) {
                if (phys <= bi->i_eblock) {
-                       dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
+                       dprintf("c=%d, b=%08lx, phys=%09lx (granted)\n",
+                                create, (unsigned long)block, phys);
                        map_bh(bh_result, sb, phys);
                }
                return 0;
@@ -80,7 +81,7 @@ static int bfs_get_block(struct inode * inode, sector_t block,
           of blocks allocated for this file, we can grant it */
        if (inode->i_size && phys <= bi->i_eblock) {
                dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 
-                               create, block, phys);
+                               create, (unsigned long)block, phys);
                map_bh(bh_result, sb, phys);
                return 0;
        }
@@ -88,11 +89,12 @@ static int bfs_get_block(struct inode * inode, sector_t block,
        /* the rest has to be protected against itself */
        lock_kernel();
 
-       /* if the last data block for this file is the last allocated block, we can
-          extend the file trivially, without moving it anywhere */
+       /* if the last data block for this file is the last allocated
+          block, we can extend the file trivially, without moving it
+          anywhere */
        if (bi->i_eblock == info->si_lf_eblk) {
                dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 
-                               create, block, phys);
+                               create, (unsigned long)block, phys);
                map_bh(bh_result, sb, phys);
                info->si_freeb -= phys - bi->i_eblock;
                info->si_lf_eblk = bi->i_eblock = phys;
@@ -114,7 +116,8 @@ static int bfs_get_block(struct inode * inode, sector_t block,
        } else
                err = 0;
 
-       dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
+       dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n",
+                create, (unsigned long)block, phys);
        bi->i_sblock = phys;
        phys += block;
        info->si_lf_eblk = bi->i_eblock = phys;
index 64e0fb33fc0cacda1dec350ca523f9ee91d10e2a..c7b39aa279d71098804570c0283d4195d54cf10a 100644 (file)
@@ -3,6 +3,8 @@
  *     BFS superblock and inode operations.
  *     Copyright (C) 1999,2000 Tigran Aivazian <tigran@veritas.com>
  *     From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
+ *
+ *      Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
  */
 
 #include <linux/module.h>
@@ -54,46 +56,50 @@ static void bfs_read_inode(struct inode * inode)
        off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
        di = (struct bfs_inode *)bh->b_data + off;
 
-       inode->i_mode = 0x0000FFFF & di->i_mode;
-       if (di->i_vtype == BFS_VDIR) {
+       inode->i_mode = 0x0000FFFF &  le32_to_cpu(di->i_mode);
+       if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
                inode->i_mode |= S_IFDIR;
                inode->i_op = &bfs_dir_inops;
                inode->i_fop = &bfs_dir_operations;
-       } else if (di->i_vtype == BFS_VREG) {
+       } else if (le32_to_cpu(di->i_vtype) == BFS_VREG) {
                inode->i_mode |= S_IFREG;
                inode->i_op = &bfs_file_inops;
                inode->i_fop = &bfs_file_operations;
                inode->i_mapping->a_ops = &bfs_aops;
        }
 
-       inode->i_uid = di->i_uid;
-       inode->i_gid = di->i_gid;
-       inode->i_nlink = di->i_nlink;
+       BFS_I(inode)->i_sblock =  le32_to_cpu(di->i_sblock);
+       BFS_I(inode)->i_eblock =  le32_to_cpu(di->i_eblock);
+       inode->i_uid =  le32_to_cpu(di->i_uid);
+       inode->i_gid =  le32_to_cpu(di->i_gid);
+       inode->i_nlink =  le32_to_cpu(di->i_nlink);
        inode->i_size = BFS_FILESIZE(di);
        inode->i_blocks = BFS_FILEBLOCKS(di);
+        if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
        inode->i_blksize = PAGE_SIZE;
-       inode->i_atime.tv_sec = di->i_atime;
-       inode->i_mtime.tv_sec = di->i_mtime;
-       inode->i_ctime.tv_sec = di->i_ctime;
+       inode->i_atime.tv_sec =  le32_to_cpu(di->i_atime);
+       inode->i_mtime.tv_sec =  le32_to_cpu(di->i_mtime);
+       inode->i_ctime.tv_sec =  le32_to_cpu(di->i_ctime);
        inode->i_atime.tv_nsec = 0;
        inode->i_mtime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       BFS_I(inode)->i_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
-       BFS_I(inode)->i_sblock = di->i_sblock;
-       BFS_I(inode)->i_eblock = di->i_eblock;
+       BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino); /* can be 0 so we store a copy */
 
        brelse(bh);
 }
 
 static int bfs_write_inode(struct inode * inode, int unused)
 {
-       unsigned long ino = inode->i_ino;
+       unsigned int ino = (u16)inode->i_ino;
+        unsigned long i_sblock;
        struct bfs_inode * di;
        struct buffer_head * bh;
        int block, off;
 
+        dprintf("ino=%08x\n", ino);
+
        if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
-               printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
+               printf("Bad inode number %s:%08x\n", inode->i_sb->s_id, ino);
                return -EIO;
        }
 
@@ -101,7 +107,7 @@ static int bfs_write_inode(struct inode * inode, int unused)
        block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
        bh = sb_bread(inode->i_sb, block);
        if (!bh) {
-               printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
+               printf("Unable to read inode %s:%08x\n", inode->i_sb->s_id, ino);
                unlock_kernel();
                return -EIO;
        }
@@ -109,24 +115,26 @@ static int bfs_write_inode(struct inode * inode, int unused)
        off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
        di = (struct bfs_inode *)bh->b_data + off;
 
-       if (inode->i_ino == BFS_ROOT_INO)
-               di->i_vtype = BFS_VDIR;
+       if (ino == BFS_ROOT_INO)
+               di->i_vtype = cpu_to_le32(BFS_VDIR);
        else
-               di->i_vtype = BFS_VREG;
-
-       di->i_ino = inode->i_ino;
-       di->i_mode = inode->i_mode;
-       di->i_uid = inode->i_uid;
-       di->i_gid = inode->i_gid;
-       di->i_nlink = inode->i_nlink;
-       di->i_atime = inode->i_atime.tv_sec;
-       di->i_mtime = inode->i_mtime.tv_sec;
-       di->i_ctime = inode->i_ctime.tv_sec;
-       di->i_sblock = BFS_I(inode)->i_sblock;
-       di->i_eblock = BFS_I(inode)->i_eblock;
-       di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
+               di->i_vtype = cpu_to_le32(BFS_VREG);
+
+       di->i_ino = cpu_to_le16(ino);
+       di->i_mode = cpu_to_le32(inode->i_mode);
+       di->i_uid = cpu_to_le32(inode->i_uid);
+       di->i_gid = cpu_to_le32(inode->i_gid);
+       di->i_nlink = cpu_to_le32(inode->i_nlink);
+       di->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
+       di->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
+       di->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
+        i_sblock = BFS_I(inode)->i_sblock;
+       di->i_sblock = cpu_to_le32(i_sblock);
+       di->i_eblock = cpu_to_le32(BFS_I(inode)->i_eblock);
+       di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
 
        mark_buffer_dirty(bh);
+        dprintf("Written ino=%d into %d:%d\n",le16_to_cpu(di->i_ino),block,off);
        brelse(bh);
        unlock_kernel();
        return 0;
@@ -140,11 +148,14 @@ static void bfs_delete_inode(struct inode * inode)
        int block, off;
        struct super_block * s = inode->i_sb;
        struct bfs_sb_info * info = BFS_SB(s);
+       struct bfs_inode_info * bi = BFS_I(inode);
 
-       dprintf("ino=%08lx\n", inode->i_ino);
+       dprintf("ino=%08lx\n", ino);
 
-       if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > info->si_lasti) {
-               printf("invalid ino=%08lx\n", inode->i_ino);
+       truncate_inode_pages(&inode->i_data, 0);
+
+       if (ino < BFS_ROOT_INO || ino > info->si_lasti) {
+               printf("invalid ino=%08lx\n", ino);
                return;
        }
        
@@ -160,13 +171,13 @@ static void bfs_delete_inode(struct inode * inode)
                return;
        }
        off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
-       di = (struct bfs_inode *)bh->b_data + off;
-       if (di->i_ino) {
-               info->si_freeb += BFS_FILEBLOCKS(di);
+       di = (struct bfs_inode *) bh->b_data + off;
+        if (bi->i_dsk_ino) {
+               info->si_freeb += 1 + bi->i_eblock - bi->i_sblock;
                info->si_freei++;
-               clear_bit(di->i_ino, info->si_imap);
+               clear_bit(ino, info->si_imap);
                dump_imap("delete_inode", s);
-       }
+        }
        di->i_ino = 0;
        di->i_sblock = 0;
        mark_buffer_dirty(bh);
@@ -272,14 +283,14 @@ static struct super_operations bfs_sops = {
 
 void dump_imap(const char *prefix, struct super_block * s)
 {
-#if 0
+#ifdef DEBUG
        int i;
        char *tmpbuf = (char *)get_zeroed_page(GFP_KERNEL);
 
        if (!tmpbuf)
                return;
        for (i=BFS_SB(s)->si_lasti; i>=0; i--) {
-               if (i>PAGE_SIZE-100) break;
+               if (i > PAGE_SIZE-100) break;
                if (test_bit(i, BFS_SB(s)->si_imap))
                        strcat(tmpbuf, "1");
                else
@@ -295,7 +306,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
        struct buffer_head * bh;
        struct bfs_super_block * bfs_sb;
        struct inode * inode;
-       int i, imap_len;
+       unsigned i, imap_len;
        struct bfs_sb_info * info;
 
        info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -310,19 +321,18 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
        if(!bh)
                goto out;
        bfs_sb = (struct bfs_super_block *)bh->b_data;
-       if (bfs_sb->s_magic != BFS_MAGIC) {
+       if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
                if (!silent)
                        printf("No BFS filesystem on %s (magic=%08x)\n", 
-                               s->s_id, bfs_sb->s_magic);
+                               s->s_id,  le32_to_cpu(bfs_sb->s_magic));
                goto out;
        }
        if (BFS_UNCLEAN(bfs_sb, s) && !silent)
                printf("%s is unclean, continuing\n", s->s_id);
 
        s->s_magic = BFS_MAGIC;
-       info->si_bfs_sb = bfs_sb;
        info->si_sbh = bh;
-       info->si_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
+       info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE)/sizeof(struct bfs_inode)
                        + BFS_ROOT_INO - 1;
 
        imap_len = info->si_lasti/8 + 1;
@@ -346,8 +356,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
                goto out;
        }
 
-       info->si_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
-       info->si_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS;
+       info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
+       info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 -  cpu_to_le32(bfs_sb->s_start))>>BFS_BSIZE_BITS;
        info->si_freei = 0;
        info->si_lf_eblk = 0;
        info->si_lf_sblk = 0;
index 1c62203a4906ec1c7ba2ca9ede00e2a2c498aeda..6cbfceabd95d78451fd16f053c6ed1b79872fbda 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/cpu.h>
 #include <linux/bitops.h>
 #include <linux/mpage.h>
+#include <linux/bit_spinlock.h>
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static void invalidate_bh_lrus(void);
index 3217ac5f6bd7aa03277307aa66a5f64573681c49..2335f14a15830902f1fff25c248d720cba799338 100644 (file)
@@ -3215,10 +3215,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
        }
        
        cifs_sb->tcon = NULL;
-       if (ses) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(HZ / 2);
-       }
+       if (ses)
+               schedule_timeout_interruptible(msecs_to_jiffies(500));
        if (ses)
                sesInfoFree(ses);
 
index 8c665705c6a07beea9a4ead55a2184524f7ed41f..ac3fb9ed8eeaf847fcd2238edb2f941d7125b7a4 100644 (file)
@@ -1619,6 +1619,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
        char *bits;
        long timeout;
        int size, max_fdset, ret = -EINVAL;
+       struct fdtable *fdt;
 
        timeout = MAX_SCHEDULE_TIMEOUT;
        if (tvp) {
@@ -1644,7 +1645,10 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
                goto out_nofds;
 
        /* max_fdset can increase, so grab it once to avoid race */
-       max_fdset = current->files->max_fdset;
+       rcu_read_lock();
+       fdt = files_fdtable(current->files);
+       max_fdset = fdt->max_fdset;
+       rcu_read_unlock();
        if (n > max_fdset)
                n = max_fdset;
 
index 155e612635f1341e1711f2546c638fa6da9dc0c5..e28a74203f3b1ae42896532a1c5e68bfb6e9c6e1 100644 (file)
@@ -798,13 +798,16 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                r = (void *) &r4;
        }
 
-       if (ret)
-               return -EFAULT;
+       if (ret) {
+               ret = -EFAULT;
+               goto out;
+       }
 
        set_fs (KERNEL_DS);
        ret = sys_ioctl (fd, cmd, (unsigned long) r);
        set_fs (old_fs);
 
+out:
        if (mysock)
                sockfd_put(mysock);
 
index 5034365b06a862ac84470d560fc1684253d598ea..8def89f2c4383b052490eeba366241adc07ccaa8 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/vmalloc.h>
 #include <linux/zlib.h>
+#include <linux/cramfs_fs.h>
 
 static z_stream stream;
 static int initialized;
index a15a2e1f55208882ec828339943894928a651bc0..7376b61269fb711c230ec1d0161119ce0672fc36 100644 (file)
@@ -337,12 +337,10 @@ struct dentry * d_find_alias(struct inode *inode)
  */
 void d_prune_aliases(struct inode *inode)
 {
-       struct list_head *tmp, *head = &inode->i_dentry;
+       struct dentry *dentry;
 restart:
        spin_lock(&dcache_lock);
-       tmp = head;
-       while ((tmp = tmp->next) != head) {
-               struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
                if (!atomic_read(&dentry->d_count)) {
                        __dget_locked(dentry);
@@ -463,10 +461,7 @@ void shrink_dcache_sb(struct super_block * sb)
         * superblock to the most recent end of the unused list.
         */
        spin_lock(&dcache_lock);
-       next = dentry_unused.next;
-       while (next != &dentry_unused) {
-               tmp = next;
-               next = tmp->next;
+       list_for_each_safe(tmp, next, &dentry_unused) {
                dentry = list_entry(tmp, struct dentry, d_lru);
                if (dentry->d_sb != sb)
                        continue;
@@ -478,10 +473,7 @@ void shrink_dcache_sb(struct super_block * sb)
         * Pass two ... free the dentries for this superblock.
         */
 repeat:
-       next = dentry_unused.next;
-       while (next != &dentry_unused) {
-               tmp = next;
-               next = tmp->next;
+       list_for_each_safe(tmp, next, &dentry_unused) {
                dentry = list_entry(tmp, struct dentry, d_lru);
                if (dentry->d_sb != sb)
                        continue;
index 222ab1c572d884762bae366086bbe145f8e0f65b..14dd03907ccb58ed1b8c9cbdce76b6246d4ce727 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -798,6 +798,7 @@ no_thread_group:
 static inline void flush_old_files(struct files_struct * files)
 {
        long j = -1;
+       struct fdtable *fdt;
 
        spin_lock(&files->file_lock);
        for (;;) {
@@ -805,12 +806,13 @@ static inline void flush_old_files(struct files_struct * files)
 
                j++;
                i = j * __NFDBITS;
-               if (i >= files->max_fds || i >= files->max_fdset)
+               fdt = files_fdtable(files);
+               if (i >= fdt->max_fds || i >= fdt->max_fdset)
                        break;
-               set = files->close_on_exec->fds_bits[j];
+               set = fdt->close_on_exec->fds_bits[j];
                if (!set)
                        continue;
-               files->close_on_exec->fds_bits[j] = 0;
+               fdt->close_on_exec->fds_bits[j] = 0;
                spin_unlock(&files->file_lock);
                for ( ; set ; i++,set >>= 1) {
                        if (set & 1) {
index 161f156d98c8635fe56194a0c6aa77768dbe3dc5..c8d07030c89725c8b4451287b867a4ba637065a3 100644 (file)
@@ -615,6 +615,11 @@ got:
                DQUOT_DROP(inode);
                goto fail2;
        }
+       err = ext2_init_security(inode,dir);
+       if (err) {
+               DQUOT_FREE_INODE(inode);
+               goto fail2;
+       }
        mark_inode_dirty(inode);
        ext2_debug("allocating inode %lu\n", inode->i_ino);
        ext2_preread_inode(inode);
index 53dceb0c659308c661a9c8e7deeced2dff27502e..fdba4d1d3c60996c438008a479975d46a81d6e3c 100644 (file)
@@ -71,6 +71,8 @@ void ext2_put_inode(struct inode *inode)
  */
 void ext2_delete_inode (struct inode * inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
+
        if (is_bad_inode(inode))
                goto no_delete;
        EXT2_I(inode)->i_dtime  = get_seconds();
index 5f3bfde3b8100adb0166945373015a47afbd7553..67cfeb66e897328869b1a34fb1c709b2aa356779 100644 (file)
@@ -116,3 +116,11 @@ exit_ext2_xattr(void)
 
 # endif  /* CONFIG_EXT2_FS_XATTR */
 
+#ifdef CONFIG_EXT2_FS_SECURITY
+extern int ext2_init_security(struct inode *inode, struct inode *dir);
+#else
+static inline int ext2_init_security(struct inode *inode, struct inode *dir)
+{
+       return 0;
+}
+#endif
index 6a6c59fbe59951d902208ef781c7a963f4617f64..a26612798471ce2d5732889c87b92be3a25faaa8 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 #include <linux/ext2_fs.h>
+#include <linux/security.h>
 #include "xattr.h"
 
 static size_t
@@ -45,6 +46,27 @@ ext2_xattr_security_set(struct inode *inode, const char *name,
                              value, size, flags);
 }
 
+int
+ext2_init_security(struct inode *inode, struct inode *dir)
+{
+       int err;
+       size_t len;
+       void *value;
+       char *name;
+
+       err = security_inode_init_security(inode, dir, &name, &value, &len);
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       return 0;
+               return err;
+       }
+       err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
+                            name, value, len, 0);
+       kfree(name);
+       kfree(value);
+       return err;
+}
+
 struct xattr_handler ext2_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = ext2_xattr_security_list,
index 6981bd014ede9f2dd6f7d902e1f2e890b1cee01f..96552769d039e64d13d2ecc80e4c356eefc4398c 100644 (file)
@@ -607,6 +607,11 @@ got:
                DQUOT_DROP(inode);
                goto fail2;
        }
+       err = ext3_init_security(handle,inode, dir);
+       if (err) {
+               DQUOT_FREE_INODE(inode);
+               goto fail2;
+       }
        err = ext3_mark_inode_dirty(handle, inode);
        if (err) {
                ext3_std_error(sb, err);
index 9989fdcf4d5aba4c00e07bd7826e9ccb639624f3..b5177c90d6f111e63fe3d13f498c4bd93306b22f 100644 (file)
@@ -187,6 +187,8 @@ void ext3_delete_inode (struct inode * inode)
 {
        handle_t *handle;
 
+       truncate_inode_pages(&inode->i_data, 0);
+
        if (is_bad_inode(inode))
                goto no_delete;
 
index eb31a69e82dc93db91ae93fcbea7995bee36b69e..2ceae38f3d49726293f36997cb5b514a7d05bc2e 100644 (file)
@@ -133,3 +133,14 @@ exit_ext3_xattr(void)
 #define ext3_xattr_handlers    NULL
 
 # endif  /* CONFIG_EXT3_FS_XATTR */
+
+#ifdef CONFIG_EXT3_FS_SECURITY
+extern int ext3_init_security(handle_t *handle, struct inode *inode,
+                               struct inode *dir);
+#else
+static inline int ext3_init_security(handle_t *handle, struct inode *inode,
+                               struct inode *dir)
+{
+       return 0;
+}
+#endif
index ddc1c41750e1403ce32c202129bb46f4bc813f06..b9c40c15647bb709e0991c2fbf25663bd4a0fa1f 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/smp_lock.h>
 #include <linux/ext3_jbd.h>
 #include <linux/ext3_fs.h>
+#include <linux/security.h>
 #include "xattr.h"
 
 static size_t
@@ -47,6 +48,27 @@ ext3_xattr_security_set(struct inode *inode, const char *name,
                              value, size, flags);
 }
 
+int
+ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
+{
+       int err;
+       size_t len;
+       void *value;
+       char *name;
+
+       err = security_inode_init_security(inode, dir, &name, &value, &len);
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       return 0;
+               return err;
+       }
+       err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
+                                   name, value, len, 0);
+       kfree(name);
+       kfree(value);
+       return err;
+}
+
 struct xattr_handler ext3_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .list   = ext3_xattr_security_list,
index 96ae85b67eba6800ab9982f0afeb041bd53bd5bf..a7cbe68e22596acfcd6cf5652aa6e07e10f57a63 100644 (file)
@@ -335,6 +335,8 @@ EXPORT_SYMBOL(fat_build_inode);
 
 static void fat_delete_inode(struct inode *inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
+
        if (!is_bad_inode(inode)) {
                inode->i_size = 0;
                fat_truncate(inode);
index 6fbc9d8fcc3621abb4af0684a79828d6f293d6b6..863b46e0d78a6594371a744358104faae657c307 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/security.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
+#include <linux/rcupdate.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
 void fastcall set_close_on_exec(unsigned int fd, int flag)
 {
        struct files_struct *files = current->files;
+       struct fdtable *fdt;
        spin_lock(&files->file_lock);
+       fdt = files_fdtable(files);
        if (flag)
-               FD_SET(fd, files->close_on_exec);
+               FD_SET(fd, fdt->close_on_exec);
        else
-               FD_CLR(fd, files->close_on_exec);
+               FD_CLR(fd, fdt->close_on_exec);
        spin_unlock(&files->file_lock);
 }
 
 static inline int get_close_on_exec(unsigned int fd)
 {
        struct files_struct *files = current->files;
+       struct fdtable *fdt;
        int res;
-       spin_lock(&files->file_lock);
-       res = FD_ISSET(fd, files->close_on_exec);
-       spin_unlock(&files->file_lock);
+       rcu_read_lock();
+       fdt = files_fdtable(files);
+       res = FD_ISSET(fd, fdt->close_on_exec);
+       rcu_read_unlock();
        return res;
 }
 
@@ -54,24 +59,26 @@ static int locate_fd(struct files_struct *files,
        unsigned int newfd;
        unsigned int start;
        int error;
+       struct fdtable *fdt;
 
        error = -EINVAL;
        if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
                goto out;
 
 repeat:
+       fdt = files_fdtable(files);
        /*
         * Someone might have closed fd's in the range
-        * orig_start..files->next_fd
+        * orig_start..fdt->next_fd
         */
        start = orig_start;
-       if (start < files->next_fd)
-               start = files->next_fd;
+       if (start < fdt->next_fd)
+               start = fdt->next_fd;
 
        newfd = start;
-       if (start < files->max_fdset) {
-               newfd = find_next_zero_bit(files->open_fds->fds_bits,
-                       files->max_fdset, start);
+       if (start < fdt->max_fdset) {
+               newfd = find_next_zero_bit(fdt->open_fds->fds_bits,
+                       fdt->max_fdset, start);
        }
        
        error = -EMFILE;
@@ -89,9 +96,15 @@ repeat:
        if (error)
                goto repeat;
 
-       if (start <= files->next_fd)
-               files->next_fd = newfd + 1;
-       
+       /*
+        * We reacquired files_lock, so we are safe as long as
+        * we reacquire the fdtable pointer and use it while holding
+        * the lock, no one can free it during that time.
+        */
+       fdt = files_fdtable(files);
+       if (start <= fdt->next_fd)
+               fdt->next_fd = newfd + 1;
+
        error = newfd;
        
 out:
@@ -101,13 +114,16 @@ out:
 static int dupfd(struct file *file, unsigned int start)
 {
        struct files_struct * files = current->files;
+       struct fdtable *fdt;
        int fd;
 
        spin_lock(&files->file_lock);
        fd = locate_fd(files, file, start);
        if (fd >= 0) {
-               FD_SET(fd, files->open_fds);
-               FD_CLR(fd, files->close_on_exec);
+               /* locate_fd() may have expanded fdtable, load the ptr */
+               fdt = files_fdtable(files);
+               FD_SET(fd, fdt->open_fds);
+               FD_CLR(fd, fdt->close_on_exec);
                spin_unlock(&files->file_lock);
                fd_install(fd, file);
        } else {
@@ -123,6 +139,7 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
        int err = -EBADF;
        struct file * file, *tofree;
        struct files_struct * files = current->files;
+       struct fdtable *fdt;
 
        spin_lock(&files->file_lock);
        if (!(file = fcheck(oldfd)))
@@ -148,13 +165,14 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd)
 
        /* Yes. It's a race. In user space. Nothing sane to do */
        err = -EBUSY;
-       tofree = files->fd[newfd];
-       if (!tofree && FD_ISSET(newfd, files->open_fds))
+       fdt = files_fdtable(files);
+       tofree = fdt->fd[newfd];
+       if (!tofree && FD_ISSET(newfd, fdt->open_fds))
                goto out_fput;
 
-       files->fd[newfd] = file;
-       FD_SET(newfd, files->open_fds);
-       FD_CLR(newfd, files->close_on_exec);
+       rcu_assign_pointer(fdt->fd[newfd], file);
+       FD_SET(newfd, fdt->open_fds);
+       FD_CLR(newfd, fdt->close_on_exec);
        spin_unlock(&files->file_lock);
 
        if (tofree)
index 92b5f25985d2f75d09022ebbe1e4a6008cd2132d..2127a7b9dc3a6ad2bb214536bf23e83d5005441b 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
 #include <linux/vmalloc.h>
 #include <linux/file.h>
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
+#include <linux/workqueue.h>
+
+struct fdtable_defer {
+       spinlock_t lock;
+       struct work_struct wq;
+       struct timer_list timer;
+       struct fdtable *next;
+};
+
+/*
+ * We use this list to defer free fdtables that have vmalloced
+ * sets/arrays. By keeping a per-cpu list, we avoid having to embed
+ * the work_struct in fdtable itself which avoids a 64 byte (i386) increase in
+ * this per-task structure.
+ */
+static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
 
 
 /*
@@ -48,82 +67,143 @@ void free_fd_array(struct file **array, int num)
                vfree(array);
 }
 
-/*
- * Expand the fd array in the files_struct.  Called with the files
- * spinlock held for write.
- */
+static void __free_fdtable(struct fdtable *fdt)
+{
+       int fdset_size, fdarray_size;
 
-static int expand_fd_array(struct files_struct *files, int nr)
-       __releases(files->file_lock)
-       __acquires(files->file_lock)
+       fdset_size = fdt->max_fdset / 8;
+       fdarray_size = fdt->max_fds * sizeof(struct file *);
+       free_fdset(fdt->open_fds, fdset_size);
+       free_fdset(fdt->close_on_exec, fdset_size);
+       free_fd_array(fdt->fd, fdarray_size);
+       kfree(fdt);
+}
+
+static void fdtable_timer(unsigned long data)
 {
-       struct file **new_fds;
-       int error, nfds;
+       struct fdtable_defer *fddef = (struct fdtable_defer *)data;
 
-       
-       error = -EMFILE;
-       if (files->max_fds >= NR_OPEN || nr >= NR_OPEN)
+       spin_lock(&fddef->lock);
+       /*
+        * If someone already emptied the queue return.
+        */
+       if (!fddef->next)
                goto out;
+       if (!schedule_work(&fddef->wq))
+               mod_timer(&fddef->timer, 5);
+out:
+       spin_unlock(&fddef->lock);
+}
 
-       nfds = files->max_fds;
-       spin_unlock(&files->file_lock);
+static void free_fdtable_work(struct fdtable_defer *f)
+{
+       struct fdtable *fdt;
 
-       /* 
-        * Expand to the max in easy steps, and keep expanding it until
-        * we have enough for the requested fd array size. 
-        */
+       spin_lock_bh(&f->lock);
+       fdt = f->next;
+       f->next = NULL;
+       spin_unlock_bh(&f->lock);
+       while(fdt) {
+               struct fdtable *next = fdt->next;
+               __free_fdtable(fdt);
+               fdt = next;
+       }
+}
 
-       do {
-#if NR_OPEN_DEFAULT < 256
-               if (nfds < 256)
-                       nfds = 256;
-               else 
-#endif
-               if (nfds < (PAGE_SIZE / sizeof(struct file *)))
-                       nfds = PAGE_SIZE / sizeof(struct file *);
-               else {
-                       nfds = nfds * 2;
-                       if (nfds > NR_OPEN)
-                               nfds = NR_OPEN;
-               }
-       } while (nfds <= nr);
+static void free_fdtable_rcu(struct rcu_head *rcu)
+{
+       struct fdtable *fdt = container_of(rcu, struct fdtable, rcu);
+       int fdset_size, fdarray_size;
+       struct fdtable_defer *fddef;
 
-       error = -ENOMEM;
-       new_fds = alloc_fd_array(nfds);
-       spin_lock(&files->file_lock);
-       if (!new_fds)
-               goto out;
+       BUG_ON(!fdt);
+       fdset_size = fdt->max_fdset / 8;
+       fdarray_size = fdt->max_fds * sizeof(struct file *);
 
-       /* Copy the existing array and install the new pointer */
-
-       if (nfds > files->max_fds) {
-               struct file **old_fds;
-               int i;
-               
-               old_fds = xchg(&files->fd, new_fds);
-               i = xchg(&files->max_fds, nfds);
-
-               /* Don't copy/clear the array if we are creating a new
-                  fd array for fork() */
-               if (i) {
-                       memcpy(new_fds, old_fds, i * sizeof(struct file *));
-                       /* clear the remainder of the array */
-                       memset(&new_fds[i], 0,
-                              (nfds-i) * sizeof(struct file *)); 
-
-                       spin_unlock(&files->file_lock);
-                       free_fd_array(old_fds, i);
-                       spin_lock(&files->file_lock);
-               }
+       if (fdt->free_files) {
+               /*
+                * The this fdtable was embedded in the files structure
+                * and the files structure itself was getting destroyed.
+                * It is now safe to free the files structure.
+                */
+               kmem_cache_free(files_cachep, fdt->free_files);
+               return;
+       }
+       if (fdt->max_fdset <= __FD_SETSIZE && fdt->max_fds <= NR_OPEN_DEFAULT) {
+               /*
+                * The fdtable was embedded
+                */
+               return;
+       }
+       if (fdset_size <= PAGE_SIZE && fdarray_size <= PAGE_SIZE) {
+               kfree(fdt->open_fds);
+               kfree(fdt->close_on_exec);
+               kfree(fdt->fd);
+               kfree(fdt);
        } else {
-               /* Somebody expanded the array while we slept ... */
-               spin_unlock(&files->file_lock);
-               free_fd_array(new_fds, nfds);
-               spin_lock(&files->file_lock);
+               fddef = &get_cpu_var(fdtable_defer_list);
+               spin_lock(&fddef->lock);
+               fdt->next = fddef->next;
+               fddef->next = fdt;
+               /*
+                * vmallocs are handled from the workqueue context.
+                * If the per-cpu workqueue is running, then we
+                * defer work scheduling through a timer.
+                */
+               if (!schedule_work(&fddef->wq))
+                       mod_timer(&fddef->timer, 5);
+               spin_unlock(&fddef->lock);
+               put_cpu_var(fdtable_defer_list);
        }
-       error = 0;
-out:
-       return error;
+}
+
+void free_fdtable(struct fdtable *fdt)
+{
+       if (fdt->free_files || fdt->max_fdset > __FD_SETSIZE ||
+                                       fdt->max_fds > NR_OPEN_DEFAULT)
+               call_rcu(&fdt->rcu, free_fdtable_rcu);
+}
+
+/*
+ * Expand the fdset in the files_struct.  Called with the files spinlock
+ * held for write.
+ */
+static void copy_fdtable(struct fdtable *nfdt, struct fdtable *fdt)
+{
+       int i;
+       int count;
+
+       BUG_ON(nfdt->max_fdset < fdt->max_fdset);
+       BUG_ON(nfdt->max_fds < fdt->max_fds);
+       /* Copy the existing tables and install the new pointers */
+
+       i = fdt->max_fdset / (sizeof(unsigned long) * 8);
+       count = (nfdt->max_fdset - fdt->max_fdset) / 8;
+
+       /*
+        * Don't copy the entire array if the current fdset is
+        * not yet initialised.
+        */
+       if (i) {
+               memcpy (nfdt->open_fds, fdt->open_fds,
+                                               fdt->max_fdset/8);
+               memcpy (nfdt->close_on_exec, fdt->close_on_exec,
+                                               fdt->max_fdset/8);
+               memset (&nfdt->open_fds->fds_bits[i], 0, count);
+               memset (&nfdt->close_on_exec->fds_bits[i], 0, count);
+       }
+
+       /* Don't copy/clear the array if we are creating a new
+          fd array for fork() */
+       if (fdt->max_fds) {
+               memcpy(nfdt->fd, fdt->fd,
+                       fdt->max_fds * sizeof(struct file *));
+               /* clear the remainder of the array */
+               memset(&nfdt->fd[fdt->max_fds], 0,
+                      (nfdt->max_fds - fdt->max_fds) *
+                                       sizeof(struct file *));
+       }
+       nfdt->next_fd = fdt->next_fd;
 }
 
 /*
@@ -154,26 +234,21 @@ void free_fdset(fd_set *array, int num)
                vfree(array);
 }
 
-/*
- * Expand the fdset in the files_struct.  Called with the files spinlock
- * held for write.
- */
-static int expand_fdset(struct files_struct *files, int nr)
-       __releases(file->file_lock)
-       __acquires(file->file_lock)
+static struct fdtable *alloc_fdtable(int nr)
 {
-       fd_set *new_openset = NULL, *new_execset = NULL;
-       int error, nfds = 0;
-
-       error = -EMFILE;
-       if (files->max_fdset >= NR_OPEN || nr >= NR_OPEN)
-               goto out;
+       struct fdtable *fdt = NULL;
+       int nfds = 0;
+       fd_set *new_openset = NULL, *new_execset = NULL;
+       struct file **new_fds;
 
-       nfds = files->max_fdset;
-       spin_unlock(&files->file_lock);
+       fdt = kmalloc(sizeof(*fdt), GFP_KERNEL);
+       if (!fdt)
+               goto out;
+       memset(fdt, 0, sizeof(*fdt));
 
-       /* Expand to the max in easy steps */
-       do {
+       nfds = __FD_SETSIZE;
+       /* Expand to the max in easy steps */
+       do {
                if (nfds < (PAGE_SIZE * 8))
                        nfds = PAGE_SIZE * 8;
                else {
@@ -183,49 +258,88 @@ static int expand_fdset(struct files_struct *files, int nr)
                }
        } while (nfds <= nr);
 
-       error = -ENOMEM;
-       new_openset = alloc_fdset(nfds);
-       new_execset = alloc_fdset(nfds);
-       spin_lock(&files->file_lock);
-       if (!new_openset || !new_execset)
+       new_openset = alloc_fdset(nfds);
+       new_execset = alloc_fdset(nfds);
+       if (!new_openset || !new_execset)
+               goto out;
+       fdt->open_fds = new_openset;
+       fdt->close_on_exec = new_execset;
+       fdt->max_fdset = nfds;
+
+       nfds = NR_OPEN_DEFAULT;
+       /*
+        * Expand to the max in easy steps, and keep expanding it until
+        * we have enough for the requested fd array size.
+        */
+       do {
+#if NR_OPEN_DEFAULT < 256
+               if (nfds < 256)
+                       nfds = 256;
+               else
+#endif
+               if (nfds < (PAGE_SIZE / sizeof(struct file *)))
+                       nfds = PAGE_SIZE / sizeof(struct file *);
+               else {
+                       nfds = nfds * 2;
+                       if (nfds > NR_OPEN)
+                               nfds = NR_OPEN;
+               }
+       } while (nfds <= nr);
+       new_fds = alloc_fd_array(nfds);
+       if (!new_fds)
+               goto out;
+       fdt->fd = new_fds;
+       fdt->max_fds = nfds;
+       fdt->free_files = NULL;
+       return fdt;
+out:
+       if (new_openset)
+               free_fdset(new_openset, nfds);
+       if (new_execset)
+               free_fdset(new_execset, nfds);
+       kfree(fdt);
+       return NULL;
+}
+
+/*
+ * Expands the file descriptor table - it will allocate a new fdtable and
+ * both fd array and fdset. It is expected to be called with the
+ * files_lock held.
+ */
+static int expand_fdtable(struct files_struct *files, int nr)
+       __releases(files->file_lock)
+       __acquires(files->file_lock)
+{
+       int error = 0;
+       struct fdtable *fdt;
+       struct fdtable *nfdt = NULL;
+
+       spin_unlock(&files->file_lock);
+       nfdt = alloc_fdtable(nr);
+       if (!nfdt) {
+               error = -ENOMEM;
+               spin_lock(&files->file_lock);
                goto out;
+       }
 
-       error = 0;
-       
-       /* Copy the existing tables and install the new pointers */
-       if (nfds > files->max_fdset) {
-               int i = files->max_fdset / (sizeof(unsigned long) * 8);
-               int count = (nfds - files->max_fdset) / 8;
-               
-               /* 
-                * Don't copy the entire array if the current fdset is
-                * not yet initialised.  
-                */
-               if (i) {
-                       memcpy (new_openset, files->open_fds, files->max_fdset/8);
-                       memcpy (new_execset, files->close_on_exec, files->max_fdset/8);
-                       memset (&new_openset->fds_bits[i], 0, count);
-                       memset (&new_execset->fds_bits[i], 0, count);
-               }
-               
-               nfds = xchg(&files->max_fdset, nfds);
-               new_openset = xchg(&files->open_fds, new_openset);
-               new_execset = xchg(&files->close_on_exec, new_execset);
+       spin_lock(&files->file_lock);
+       fdt = files_fdtable(files);
+       /*
+        * Check again since another task may have expanded the
+        * fd table while we dropped the lock
+        */
+       if (nr >= fdt->max_fds || nr >= fdt->max_fdset) {
+               copy_fdtable(nfdt, fdt);
+       } else {
+               /* Somebody expanded while we dropped file_lock */
                spin_unlock(&files->file_lock);
-               free_fdset (new_openset, nfds);
-               free_fdset (new_execset, nfds);
+               __free_fdtable(nfdt);
                spin_lock(&files->file_lock);
-               return 0;
-       } 
-       /* Somebody expanded the array while we slept ... */
-
+               goto out;
+       }
+       rcu_assign_pointer(files->fdt, nfdt);
+       free_fdtable(fdt);
 out:
-       spin_unlock(&files->file_lock);
-       if (new_openset)
-               free_fdset(new_openset, nfds);
-       if (new_execset)
-               free_fdset(new_execset, nfds);
-       spin_lock(&files->file_lock);
        return error;
 }
 
@@ -237,18 +351,39 @@ out:
 int expand_files(struct files_struct *files, int nr)
 {
        int err, expand = 0;
+       struct fdtable *fdt;
 
-       if (nr >= files->max_fdset) {
-               expand = 1;
-               if ((err = expand_fdset(files, nr)))
+       fdt = files_fdtable(files);
+       if (nr >= fdt->max_fdset || nr >= fdt->max_fds) {
+               if (fdt->max_fdset >= NR_OPEN ||
+                       fdt->max_fds >= NR_OPEN || nr >= NR_OPEN) {
+                       err = -EMFILE;
                        goto out;
-       }
-       if (nr >= files->max_fds) {
+               }
                expand = 1;
-               if ((err = expand_fd_array(files, nr)))
+               if ((err = expand_fdtable(files, nr)))
                        goto out;
        }
        err = expand;
 out:
        return err;
 }
+
+static void __devinit fdtable_defer_list_init(int cpu)
+{
+       struct fdtable_defer *fddef = &per_cpu(fdtable_defer_list, cpu);
+       spin_lock_init(&fddef->lock);
+       INIT_WORK(&fddef->wq, (void (*)(void *))free_fdtable_work, fddef);
+       init_timer(&fddef->timer);
+       fddef->timer.data = (unsigned long)fddef;
+       fddef->timer.function = fdtable_timer;
+       fddef->next = NULL;
+}
+
+void __init files_defer_init(void)
+{
+       int i;
+       /* Really early - can't use for_each_cpu */
+       for (i = 0; i < NR_CPUS; i++)
+               fdtable_defer_list_init(i);
+}
index 43e9e1737de2cb365c954afeddfb64ae0433779b..86ec8ae985b413bd3d8b135ff8dfd9fe305ef5bf 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/eventpoll.h>
+#include <linux/rcupdate.h>
 #include <linux/mount.h>
 #include <linux/cdev.h>
 #include <linux/fsnotify.h>
@@ -53,11 +54,17 @@ void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags)
        spin_unlock_irqrestore(&filp_count_lock, flags);
 }
 
-static inline void file_free(struct file *f)
+static inline void file_free_rcu(struct rcu_head *head)
 {
+       struct file *f =  container_of(head, struct file, f_rcuhead);
        kmem_cache_free(filp_cachep, f);
 }
 
+static inline void file_free(struct file *f)
+{
+       call_rcu(&f->f_rcuhead, file_free_rcu);
+}
+
 /* Find an unused file structure and return a pointer to it.
  * Returns NULL, if there are no more free file structures or
  * we run out of memory.
@@ -110,7 +117,7 @@ EXPORT_SYMBOL(get_empty_filp);
 
 void fastcall fput(struct file *file)
 {
-       if (atomic_dec_and_test(&file->f_count))
+       if (rcuref_dec_and_test(&file->f_count))
                __fput(file);
 }
 
@@ -156,11 +163,17 @@ struct file fastcall *fget(unsigned int fd)
        struct file *file;
        struct files_struct *files = current->files;
 
-       spin_lock(&files->file_lock);
+       rcu_read_lock();
        file = fcheck_files(files, fd);
-       if (file)
-               get_file(file);
-       spin_unlock(&files->file_lock);
+       if (file) {
+               if (!rcuref_inc_lf(&file->f_count)) {
+                       /* File object ref couldn't be taken */
+                       rcu_read_unlock();
+                       return NULL;
+               }
+       }
+       rcu_read_unlock();
+
        return file;
 }
 
@@ -182,21 +195,25 @@ struct file fastcall *fget_light(unsigned int fd, int *fput_needed)
        if (likely((atomic_read(&files->count) == 1))) {
                file = fcheck_files(files, fd);
        } else {
-               spin_lock(&files->file_lock);
+               rcu_read_lock();
                file = fcheck_files(files, fd);
                if (file) {
-                       get_file(file);
-                       *fput_needed = 1;
+                       if (rcuref_inc_lf(&file->f_count))
+                               *fput_needed = 1;
+                       else
+                               /* Didn't get the reference, someone's freed */
+                               file = NULL;
                }
-               spin_unlock(&files->file_lock);
+               rcu_read_unlock();
        }
+
        return file;
 }
 
 
 void put_filp(struct file *file)
 {
-       if (atomic_dec_and_test(&file->f_count)) {
+       if (rcuref_dec_and_test(&file->f_count)) {
                security_file_free(file);
                file_kill(file);
                file_free(file);
@@ -257,4 +274,5 @@ void __init files_init(unsigned long mempages)
        files_stat.max_files = n; 
        if (files_stat.max_files < NR_FILE)
                files_stat.max_files = NR_FILE;
+       files_defer_init();
 } 
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
new file mode 100644 (file)
index 0000000..c3e1f76
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the FUSE filesystem.
+#
+
+obj-$(CONFIG_FUSE_FS) += fuse.o
+
+fuse-objs := dev.o dir.o file.o inode.o
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
new file mode 100644 (file)
index 0000000..d4c869c
--- /dev/null
@@ -0,0 +1,877 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/uio.h>
+#include <linux/miscdevice.h>
+#include <linux/pagemap.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+MODULE_ALIAS_MISCDEV(FUSE_MINOR);
+
+static kmem_cache_t *fuse_req_cachep;
+
+static inline struct fuse_conn *fuse_get_conn(struct file *file)
+{
+       struct fuse_conn *fc;
+       spin_lock(&fuse_lock);
+       fc = file->private_data;
+       if (fc && !fc->mounted)
+               fc = NULL;
+       spin_unlock(&fuse_lock);
+       return fc;
+}
+
+static inline void fuse_request_init(struct fuse_req *req)
+{
+       memset(req, 0, sizeof(*req));
+       INIT_LIST_HEAD(&req->list);
+       init_waitqueue_head(&req->waitq);
+       atomic_set(&req->count, 1);
+}
+
+struct fuse_req *fuse_request_alloc(void)
+{
+       struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, SLAB_KERNEL);
+       if (req)
+               fuse_request_init(req);
+       return req;
+}
+
+void fuse_request_free(struct fuse_req *req)
+{
+       kmem_cache_free(fuse_req_cachep, req);
+}
+
+static inline void block_sigs(sigset_t *oldset)
+{
+       sigset_t mask;
+
+       siginitsetinv(&mask, sigmask(SIGKILL));
+       sigprocmask(SIG_BLOCK, &mask, oldset);
+}
+
+static inline void restore_sigs(sigset_t *oldset)
+{
+       sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
+void fuse_reset_request(struct fuse_req *req)
+{
+       int preallocated = req->preallocated;
+       BUG_ON(atomic_read(&req->count) != 1);
+       fuse_request_init(req);
+       req->preallocated = preallocated;
+}
+
+static void __fuse_get_request(struct fuse_req *req)
+{
+       atomic_inc(&req->count);
+}
+
+/* Must be called with > 1 refcount */
+static void __fuse_put_request(struct fuse_req *req)
+{
+       BUG_ON(atomic_read(&req->count) < 2);
+       atomic_dec(&req->count);
+}
+
+static struct fuse_req *do_get_request(struct fuse_conn *fc)
+{
+       struct fuse_req *req;
+
+       spin_lock(&fuse_lock);
+       BUG_ON(list_empty(&fc->unused_list));
+       req = list_entry(fc->unused_list.next, struct fuse_req, list);
+       list_del_init(&req->list);
+       spin_unlock(&fuse_lock);
+       fuse_request_init(req);
+       req->preallocated = 1;
+       req->in.h.uid = current->fsuid;
+       req->in.h.gid = current->fsgid;
+       req->in.h.pid = current->pid;
+       return req;
+}
+
+/* This can return NULL, but only in case it's interrupted by a SIGKILL */
+struct fuse_req *fuse_get_request(struct fuse_conn *fc)
+{
+       int intr;
+       sigset_t oldset;
+
+       block_sigs(&oldset);
+       intr = down_interruptible(&fc->outstanding_sem);
+       restore_sigs(&oldset);
+       return intr ? NULL : do_get_request(fc);
+}
+
+static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+       spin_lock(&fuse_lock);
+       if (req->preallocated)
+               list_add(&req->list, &fc->unused_list);
+       else
+               fuse_request_free(req);
+
+       /* If we are in debt decrease that first */
+       if (fc->outstanding_debt)
+               fc->outstanding_debt--;
+       else
+               up(&fc->outstanding_sem);
+       spin_unlock(&fuse_lock);
+}
+
+void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+       if (atomic_dec_and_test(&req->count))
+               fuse_putback_request(fc, req);
+}
+
+void fuse_release_background(struct fuse_req *req)
+{
+       iput(req->inode);
+       iput(req->inode2);
+       if (req->file)
+               fput(req->file);
+       spin_lock(&fuse_lock);
+       list_del(&req->bg_entry);
+       spin_unlock(&fuse_lock);
+}
+
+/*
+ * This function is called when a request is finished.  Either a reply
+ * has arrived or it was interrupted (and not yet sent) or some error
+ * occured during communication with userspace, or the device file was
+ * closed.  It decreases the referece count for the request.  In case
+ * of a background request the referece to the stored objects are
+ * released.  The requester thread is woken up (if still waiting), and
+ * finally the request is either freed or put on the unused_list
+ *
+ * Called with fuse_lock, unlocks it
+ */
+static void request_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+       int putback;
+       req->finished = 1;
+       putback = atomic_dec_and_test(&req->count);
+       spin_unlock(&fuse_lock);
+       if (req->background) {
+               down_read(&fc->sbput_sem);
+               if (fc->mounted)
+                       fuse_release_background(req);
+               up_read(&fc->sbput_sem);
+       }
+       wake_up(&req->waitq);
+       if (req->in.h.opcode == FUSE_INIT) {
+               int i;
+
+               if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION)
+                       fc->conn_error = 1;
+
+               /* After INIT reply is received other requests can go
+                  out.  So do (FUSE_MAX_OUTSTANDING - 1) number of
+                  up()s on outstanding_sem.  The last up() is done in
+                  fuse_putback_request() */
+               for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
+                       up(&fc->outstanding_sem);
+       }
+       if (putback)
+               fuse_putback_request(fc, req);
+}
+
+/*
+ * Unfortunately request interruption not just solves the deadlock
+ * problem, it causes problems too.  These stem from the fact, that an
+ * interrupted request is continued to be processed in userspace,
+ * while all the locks and object references (inode and file) held
+ * during the operation are released.
+ *
+ * To release the locks is exactly why there's a need to interrupt the
+ * request, so there's not a lot that can be done about this, except
+ * introduce additional locking in userspace.
+ *
+ * More important is to keep inode and file references until userspace
+ * has replied, otherwise FORGET and RELEASE could be sent while the
+ * inode/file is still used by the filesystem.
+ *
+ * For this reason the concept of "background" request is introduced.
+ * An interrupted request is backgrounded if it has been already sent
+ * to userspace.  Backgrounding involves getting an extra reference to
+ * inode(s) or file used in the request, and adding the request to
+ * fc->background list.  When a reply is received for a background
+ * request, the object references are released, and the request is
+ * removed from the list.  If the filesystem is unmounted while there
+ * are still background requests, the list is walked and references
+ * are released as if a reply was received.
+ *
+ * There's one more use for a background request.  The RELEASE message is
+ * always sent as background, since it doesn't return an error or
+ * data.
+ */
+static void background_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+       req->background = 1;
+       list_add(&req->bg_entry, &fc->background);
+       if (req->inode)
+               req->inode = igrab(req->inode);
+       if (req->inode2)
+               req->inode2 = igrab(req->inode2);
+       if (req->file)
+               get_file(req->file);
+}
+
+/* Called with fuse_lock held.  Releases, and then reacquires it. */
+static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
+{
+       sigset_t oldset;
+
+       spin_unlock(&fuse_lock);
+       block_sigs(&oldset);
+       wait_event_interruptible(req->waitq, req->finished);
+       restore_sigs(&oldset);
+       spin_lock(&fuse_lock);
+       if (req->finished)
+               return;
+
+       req->out.h.error = -EINTR;
+       req->interrupted = 1;
+       if (req->locked) {
+               /* This is uninterruptible sleep, because data is
+                  being copied to/from the buffers of req.  During
+                  locked state, there mustn't be any filesystem
+                  operation (e.g. page fault), since that could lead
+                  to deadlock */
+               spin_unlock(&fuse_lock);
+               wait_event(req->waitq, !req->locked);
+               spin_lock(&fuse_lock);
+       }
+       if (!req->sent && !list_empty(&req->list)) {
+               list_del(&req->list);
+               __fuse_put_request(req);
+       } else if (!req->finished && req->sent)
+               background_request(fc, req);
+}
+
+static unsigned len_args(unsigned numargs, struct fuse_arg *args)
+{
+       unsigned nbytes = 0;
+       unsigned i;
+
+       for (i = 0; i < numargs; i++)
+               nbytes += args[i].size;
+
+       return nbytes;
+}
+
+static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+       fc->reqctr++;
+       /* zero is special */
+       if (fc->reqctr == 0)
+               fc->reqctr = 1;
+       req->in.h.unique = fc->reqctr;
+       req->in.h.len = sizeof(struct fuse_in_header) +
+               len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
+       if (!req->preallocated) {
+               /* If request is not preallocated (either FORGET or
+                  RELEASE), then still decrease outstanding_sem, so
+                  user can't open infinite number of files while not
+                  processing the RELEASE requests.  However for
+                  efficiency do it without blocking, so if down()
+                  would block, just increase the debt instead */
+               if (down_trylock(&fc->outstanding_sem))
+                       fc->outstanding_debt++;
+       }
+       list_add_tail(&req->list, &fc->pending);
+       wake_up(&fc->waitq);
+}
+
+/*
+ * This can only be interrupted by a SIGKILL
+ */
+void request_send(struct fuse_conn *fc, struct fuse_req *req)
+{
+       req->isreply = 1;
+       spin_lock(&fuse_lock);
+       if (!fc->connected)
+               req->out.h.error = -ENOTCONN;
+       else if (fc->conn_error)
+               req->out.h.error = -ECONNREFUSED;
+       else {
+               queue_request(fc, req);
+               /* acquire extra reference, since request is still needed
+                  after request_end() */
+               __fuse_get_request(req);
+
+               request_wait_answer(fc, req);
+       }
+       spin_unlock(&fuse_lock);
+}
+
+static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
+{
+       spin_lock(&fuse_lock);
+       if (fc->connected) {
+               queue_request(fc, req);
+               spin_unlock(&fuse_lock);
+       } else {
+               req->out.h.error = -ENOTCONN;
+               request_end(fc, req);
+       }
+}
+
+void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req)
+{
+       req->isreply = 0;
+       request_send_nowait(fc, req);
+}
+
+void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
+{
+       req->isreply = 1;
+       spin_lock(&fuse_lock);
+       background_request(fc, req);
+       spin_unlock(&fuse_lock);
+       request_send_nowait(fc, req);
+}
+
+void fuse_send_init(struct fuse_conn *fc)
+{
+       /* This is called from fuse_read_super() so there's guaranteed
+          to be a request available */
+       struct fuse_req *req = do_get_request(fc);
+       struct fuse_init_in_out *arg = &req->misc.init_in_out;
+       arg->major = FUSE_KERNEL_VERSION;
+       arg->minor = FUSE_KERNEL_MINOR_VERSION;
+       req->in.h.opcode = FUSE_INIT;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(*arg);
+       req->in.args[0].value = arg;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(*arg);
+       req->out.args[0].value = arg;
+       request_send_background(fc, req);
+}
+
+/*
+ * Lock the request.  Up to the next unlock_request() there mustn't be
+ * anything that could cause a page-fault.  If the request was already
+ * interrupted bail out.
+ */
+static inline int lock_request(struct fuse_req *req)
+{
+       int err = 0;
+       if (req) {
+               spin_lock(&fuse_lock);
+               if (req->interrupted)
+                       err = -ENOENT;
+               else
+                       req->locked = 1;
+               spin_unlock(&fuse_lock);
+       }
+       return err;
+}
+
+/*
+ * Unlock request.  If it was interrupted during being locked, the
+ * requester thread is currently waiting for it to be unlocked, so
+ * wake it up.
+ */
+static inline void unlock_request(struct fuse_req *req)
+{
+       if (req) {
+               spin_lock(&fuse_lock);
+               req->locked = 0;
+               if (req->interrupted)
+                       wake_up(&req->waitq);
+               spin_unlock(&fuse_lock);
+       }
+}
+
+struct fuse_copy_state {
+       int write;
+       struct fuse_req *req;
+       const struct iovec *iov;
+       unsigned long nr_segs;
+       unsigned long seglen;
+       unsigned long addr;
+       struct page *pg;
+       void *mapaddr;
+       void *buf;
+       unsigned len;
+};
+
+static void fuse_copy_init(struct fuse_copy_state *cs, int write,
+                          struct fuse_req *req, const struct iovec *iov,
+                          unsigned long nr_segs)
+{
+       memset(cs, 0, sizeof(*cs));
+       cs->write = write;
+       cs->req = req;
+       cs->iov = iov;
+       cs->nr_segs = nr_segs;
+}
+
+/* Unmap and put previous page of userspace buffer */
+static inline void fuse_copy_finish(struct fuse_copy_state *cs)
+{
+       if (cs->mapaddr) {
+               kunmap_atomic(cs->mapaddr, KM_USER0);
+               if (cs->write) {
+                       flush_dcache_page(cs->pg);
+                       set_page_dirty_lock(cs->pg);
+               }
+               put_page(cs->pg);
+               cs->mapaddr = NULL;
+       }
+}
+
+/*
+ * Get another pagefull of userspace buffer, and map it to kernel
+ * address space, and lock request
+ */
+static int fuse_copy_fill(struct fuse_copy_state *cs)
+{
+       unsigned long offset;
+       int err;
+
+       unlock_request(cs->req);
+       fuse_copy_finish(cs);
+       if (!cs->seglen) {
+               BUG_ON(!cs->nr_segs);
+               cs->seglen = cs->iov[0].iov_len;
+               cs->addr = (unsigned long) cs->iov[0].iov_base;
+               cs->iov ++;
+               cs->nr_segs --;
+       }
+       down_read(&current->mm->mmap_sem);
+       err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
+                            &cs->pg, NULL);
+       up_read(&current->mm->mmap_sem);
+       if (err < 0)
+               return err;
+       BUG_ON(err != 1);
+       offset = cs->addr % PAGE_SIZE;
+       cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
+       cs->buf = cs->mapaddr + offset;
+       cs->len = min(PAGE_SIZE - offset, cs->seglen);
+       cs->seglen -= cs->len;
+       cs->addr += cs->len;
+
+       return lock_request(cs->req);
+}
+
+/* Do as much copy to/from userspace buffer as we can */
+static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val,
+                              unsigned *size)
+{
+       unsigned ncpy = min(*size, cs->len);
+       if (val) {
+               if (cs->write)
+                       memcpy(cs->buf, *val, ncpy);
+               else
+                       memcpy(*val, cs->buf, ncpy);
+               *val += ncpy;
+       }
+       *size -= ncpy;
+       cs->len -= ncpy;
+       cs->buf += ncpy;
+       return ncpy;
+}
+
+/*
+ * Copy a page in the request to/from the userspace buffer.  Must be
+ * done atomically
+ */
+static inline int fuse_copy_page(struct fuse_copy_state *cs, struct page *page,
+                                unsigned offset, unsigned count, int zeroing)
+{
+       if (page && zeroing && count < PAGE_SIZE) {
+               void *mapaddr = kmap_atomic(page, KM_USER1);
+               memset(mapaddr, 0, PAGE_SIZE);
+               kunmap_atomic(mapaddr, KM_USER1);
+       }
+       while (count) {
+               int err;
+               if (!cs->len && (err = fuse_copy_fill(cs)))
+                       return err;
+               if (page) {
+                       void *mapaddr = kmap_atomic(page, KM_USER1);
+                       void *buf = mapaddr + offset;
+                       offset += fuse_copy_do(cs, &buf, &count);
+                       kunmap_atomic(mapaddr, KM_USER1);
+               } else
+                       offset += fuse_copy_do(cs, NULL, &count);
+       }
+       if (page && !cs->write)
+               flush_dcache_page(page);
+       return 0;
+}
+
+/* Copy pages in the request to/from userspace buffer */
+static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
+                          int zeroing)
+{
+       unsigned i;
+       struct fuse_req *req = cs->req;
+       unsigned offset = req->page_offset;
+       unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
+
+       for (i = 0; i < req->num_pages && (nbytes || zeroing); i++) {
+               struct page *page = req->pages[i];
+               int err = fuse_copy_page(cs, page, offset, count, zeroing);
+               if (err)
+                       return err;
+
+               nbytes -= count;
+               count = min(nbytes, (unsigned) PAGE_SIZE);
+               offset = 0;
+       }
+       return 0;
+}
+
+/* Copy a single argument in the request to/from userspace buffer */
+static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
+{
+       while (size) {
+               int err;
+               if (!cs->len && (err = fuse_copy_fill(cs)))
+                       return err;
+               fuse_copy_do(cs, &val, &size);
+       }
+       return 0;
+}
+
+/* Copy request arguments to/from userspace buffer */
+static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
+                         unsigned argpages, struct fuse_arg *args,
+                         int zeroing)
+{
+       int err = 0;
+       unsigned i;
+
+       for (i = 0; !err && i < numargs; i++)  {
+               struct fuse_arg *arg = &args[i];
+               if (i == numargs - 1 && argpages)
+                       err = fuse_copy_pages(cs, arg->size, zeroing);
+               else
+                       err = fuse_copy_one(cs, arg->value, arg->size);
+       }
+       return err;
+}
+
+/* Wait until a request is available on the pending list */
+static void request_wait(struct fuse_conn *fc)
+{
+       DECLARE_WAITQUEUE(wait, current);
+
+       add_wait_queue_exclusive(&fc->waitq, &wait);
+       while (fc->mounted && list_empty(&fc->pending)) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (signal_pending(current))
+                       break;
+
+               spin_unlock(&fuse_lock);
+               schedule();
+               spin_lock(&fuse_lock);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&fc->waitq, &wait);
+}
+
+/*
+ * Read a single request into the userspace filesystem's buffer.  This
+ * function waits until a request is available, then removes it from
+ * the pending list and copies request data to userspace buffer.  If
+ * no reply is needed (FORGET) or request has been interrupted or
+ * there was an error during the copying then it's finished by calling
+ * request_end().  Otherwise add it to the processing list, and set
+ * the 'sent' flag.
+ */
+static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
+                             unsigned long nr_segs, loff_t *off)
+{
+       int err;
+       struct fuse_conn *fc;
+       struct fuse_req *req;
+       struct fuse_in *in;
+       struct fuse_copy_state cs;
+       unsigned reqsize;
+
+       spin_lock(&fuse_lock);
+       fc = file->private_data;
+       err = -EPERM;
+       if (!fc)
+               goto err_unlock;
+       request_wait(fc);
+       err = -ENODEV;
+       if (!fc->mounted)
+               goto err_unlock;
+       err = -ERESTARTSYS;
+       if (list_empty(&fc->pending))
+               goto err_unlock;
+
+       req = list_entry(fc->pending.next, struct fuse_req, list);
+       list_del_init(&req->list);
+       spin_unlock(&fuse_lock);
+
+       in = &req->in;
+       reqsize = req->in.h.len;
+       fuse_copy_init(&cs, 1, req, iov, nr_segs);
+       err = -EINVAL;
+       if (iov_length(iov, nr_segs) >= reqsize) {
+               err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
+               if (!err)
+                       err = fuse_copy_args(&cs, in->numargs, in->argpages,
+                                            (struct fuse_arg *) in->args, 0);
+       }
+       fuse_copy_finish(&cs);
+
+       spin_lock(&fuse_lock);
+       req->locked = 0;
+       if (!err && req->interrupted)
+               err = -ENOENT;
+       if (err) {
+               if (!req->interrupted)
+                       req->out.h.error = -EIO;
+               request_end(fc, req);
+               return err;
+       }
+       if (!req->isreply)
+               request_end(fc, req);
+       else {
+               req->sent = 1;
+               list_add_tail(&req->list, &fc->processing);
+               spin_unlock(&fuse_lock);
+       }
+       return reqsize;
+
+ err_unlock:
+       spin_unlock(&fuse_lock);
+       return err;
+}
+
+static ssize_t fuse_dev_read(struct file *file, char __user *buf,
+                            size_t nbytes, loff_t *off)
+{
+       struct iovec iov;
+       iov.iov_len = nbytes;
+       iov.iov_base = buf;
+       return fuse_dev_readv(file, &iov, 1, off);
+}
+
+/* Look up request on processing list by unique ID */
+static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
+{
+       struct list_head *entry;
+
+       list_for_each(entry, &fc->processing) {
+               struct fuse_req *req;
+               req = list_entry(entry, struct fuse_req, list);
+               if (req->in.h.unique == unique)
+                       return req;
+       }
+       return NULL;
+}
+
+static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
+                        unsigned nbytes)
+{
+       unsigned reqsize = sizeof(struct fuse_out_header);
+
+       if (out->h.error)
+               return nbytes != reqsize ? -EINVAL : 0;
+
+       reqsize += len_args(out->numargs, out->args);
+
+       if (reqsize < nbytes || (reqsize > nbytes && !out->argvar))
+               return -EINVAL;
+       else if (reqsize > nbytes) {
+               struct fuse_arg *lastarg = &out->args[out->numargs-1];
+               unsigned diffsize = reqsize - nbytes;
+               if (diffsize > lastarg->size)
+                       return -EINVAL;
+               lastarg->size -= diffsize;
+       }
+       return fuse_copy_args(cs, out->numargs, out->argpages, out->args,
+                             out->page_zeroing);
+}
+
+/*
+ * Write a single reply to a request.  First the header is copied from
+ * the write buffer.  The request is then searched on the processing
+ * list by the unique ID found in the header.  If found, then remove
+ * it from the list and copy the rest of the buffer to the request.
+ * The request is finished by calling request_end()
+ */
+static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
+                              unsigned long nr_segs, loff_t *off)
+{
+       int err;
+       unsigned nbytes = iov_length(iov, nr_segs);
+       struct fuse_req *req;
+       struct fuse_out_header oh;
+       struct fuse_copy_state cs;
+       struct fuse_conn *fc = fuse_get_conn(file);
+       if (!fc)
+               return -ENODEV;
+
+       fuse_copy_init(&cs, 0, NULL, iov, nr_segs);
+       if (nbytes < sizeof(struct fuse_out_header))
+               return -EINVAL;
+
+       err = fuse_copy_one(&cs, &oh, sizeof(oh));
+       if (err)
+               goto err_finish;
+       err = -EINVAL;
+       if (!oh.unique || oh.error <= -1000 || oh.error > 0 ||
+           oh.len != nbytes)
+               goto err_finish;
+
+       spin_lock(&fuse_lock);
+       req = request_find(fc, oh.unique);
+       err = -EINVAL;
+       if (!req)
+               goto err_unlock;
+
+       list_del_init(&req->list);
+       if (req->interrupted) {
+               request_end(fc, req);
+               fuse_copy_finish(&cs);
+               return -ENOENT;
+       }
+       req->out.h = oh;
+       req->locked = 1;
+       cs.req = req;
+       spin_unlock(&fuse_lock);
+
+       err = copy_out_args(&cs, &req->out, nbytes);
+       fuse_copy_finish(&cs);
+
+       spin_lock(&fuse_lock);
+       req->locked = 0;
+       if (!err) {
+               if (req->interrupted)
+                       err = -ENOENT;
+       } else if (!req->interrupted)
+               req->out.h.error = -EIO;
+       request_end(fc, req);
+
+       return err ? err : nbytes;
+
+ err_unlock:
+       spin_unlock(&fuse_lock);
+ err_finish:
+       fuse_copy_finish(&cs);
+       return err;
+}
+
+static ssize_t fuse_dev_write(struct file *file, const char __user *buf,
+                             size_t nbytes, loff_t *off)
+{
+       struct iovec iov;
+       iov.iov_len = nbytes;
+       iov.iov_base = (char __user *) buf;
+       return fuse_dev_writev(file, &iov, 1, off);
+}
+
+static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
+{
+       struct fuse_conn *fc = fuse_get_conn(file);
+       unsigned mask = POLLOUT | POLLWRNORM;
+
+       if (!fc)
+               return -ENODEV;
+
+       poll_wait(file, &fc->waitq, wait);
+
+       spin_lock(&fuse_lock);
+       if (!list_empty(&fc->pending))
+                mask |= POLLIN | POLLRDNORM;
+       spin_unlock(&fuse_lock);
+
+       return mask;
+}
+
+/* Abort all requests on the given list (pending or processing) */
+static void end_requests(struct fuse_conn *fc, struct list_head *head)
+{
+       while (!list_empty(head)) {
+               struct fuse_req *req;
+               req = list_entry(head->next, struct fuse_req, list);
+               list_del_init(&req->list);
+               req->out.h.error = -ECONNABORTED;
+               request_end(fc, req);
+               spin_lock(&fuse_lock);
+       }
+}
+
+static int fuse_dev_release(struct inode *inode, struct file *file)
+{
+       struct fuse_conn *fc;
+
+       spin_lock(&fuse_lock);
+       fc = file->private_data;
+       if (fc) {
+               fc->connected = 0;
+               end_requests(fc, &fc->pending);
+               end_requests(fc, &fc->processing);
+               fuse_release_conn(fc);
+       }
+       spin_unlock(&fuse_lock);
+       return 0;
+}
+
+struct file_operations fuse_dev_operations = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = fuse_dev_read,
+       .readv          = fuse_dev_readv,
+       .write          = fuse_dev_write,
+       .writev         = fuse_dev_writev,
+       .poll           = fuse_dev_poll,
+       .release        = fuse_dev_release,
+};
+
+static struct miscdevice fuse_miscdevice = {
+       .minor = FUSE_MINOR,
+       .name  = "fuse",
+       .fops = &fuse_dev_operations,
+};
+
+int __init fuse_dev_init(void)
+{
+       int err = -ENOMEM;
+       fuse_req_cachep = kmem_cache_create("fuse_request",
+                                           sizeof(struct fuse_req),
+                                           0, 0, NULL, NULL);
+       if (!fuse_req_cachep)
+               goto out;
+
+       err = misc_register(&fuse_miscdevice);
+       if (err)
+               goto out_cache_clean;
+
+       return 0;
+
+ out_cache_clean:
+       kmem_cache_destroy(fuse_req_cachep);
+ out:
+       return err;
+}
+
+void fuse_dev_cleanup(void)
+{
+       misc_deregister(&fuse_miscdevice);
+       kmem_cache_destroy(fuse_req_cachep);
+}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
new file mode 100644 (file)
index 0000000..e79e49b
--- /dev/null
@@ -0,0 +1,982 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/pagemap.h>
+#include <linux/file.h>
+#include <linux/gfp.h>
+#include <linux/sched.h>
+#include <linux/namei.h>
+
+static inline unsigned long time_to_jiffies(unsigned long sec,
+                                           unsigned long nsec)
+{
+       struct timespec ts = {sec, nsec};
+       return jiffies + timespec_to_jiffies(&ts);
+}
+
+static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
+                            struct dentry *entry,
+                            struct fuse_entry_out *outarg)
+{
+       req->in.h.opcode = FUSE_LOOKUP;
+       req->in.h.nodeid = get_node_id(dir);
+       req->inode = dir;
+       req->in.numargs = 1;
+       req->in.args[0].size = entry->d_name.len + 1;
+       req->in.args[0].value = entry->d_name.name;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(struct fuse_entry_out);
+       req->out.args[0].value = outarg;
+}
+
+static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
+{
+       if (!entry->d_inode || is_bad_inode(entry->d_inode))
+               return 0;
+       else if (time_after(jiffies, entry->d_time)) {
+               int err;
+               struct fuse_entry_out outarg;
+               struct inode *inode = entry->d_inode;
+               struct fuse_inode *fi = get_fuse_inode(inode);
+               struct fuse_conn *fc = get_fuse_conn(inode);
+               struct fuse_req *req = fuse_get_request(fc);
+               if (!req)
+                       return 0;
+
+               fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg);
+               request_send(fc, req);
+               err = req->out.h.error;
+               if (!err) {
+                       if (outarg.nodeid != get_node_id(inode)) {
+                               fuse_send_forget(fc, req, outarg.nodeid, 1);
+                               return 0;
+                       }
+                       fi->nlookup ++;
+               }
+               fuse_put_request(fc, req);
+               if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
+                       return 0;
+
+               fuse_change_attributes(inode, &outarg.attr);
+               entry->d_time = time_to_jiffies(outarg.entry_valid,
+                                               outarg.entry_valid_nsec);
+               fi->i_time = time_to_jiffies(outarg.attr_valid,
+                                            outarg.attr_valid_nsec);
+       }
+       return 1;
+}
+
+static struct dentry_operations fuse_dentry_operations = {
+       .d_revalidate   = fuse_dentry_revalidate,
+};
+
+static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
+                           struct inode **inodep)
+{
+       int err;
+       struct fuse_entry_out outarg;
+       struct inode *inode = NULL;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct fuse_req *req;
+
+       if (entry->d_name.len > FUSE_NAME_MAX)
+               return -ENAMETOOLONG;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       fuse_lookup_init(req, dir, entry, &outarg);
+       request_send(fc, req);
+       err = req->out.h.error;
+       if (!err) {
+               inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
+                                 &outarg.attr);
+               if (!inode) {
+                       fuse_send_forget(fc, req, outarg.nodeid, 1);
+                       return -ENOMEM;
+               }
+       }
+       fuse_put_request(fc, req);
+       if (err && err != -ENOENT)
+               return err;
+
+       if (inode) {
+               struct fuse_inode *fi = get_fuse_inode(inode);
+               entry->d_time = time_to_jiffies(outarg.entry_valid,
+                                               outarg.entry_valid_nsec);
+               fi->i_time = time_to_jiffies(outarg.attr_valid,
+                                            outarg.attr_valid_nsec);
+       }
+
+       entry->d_op = &fuse_dentry_operations;
+       *inodep = inode;
+       return 0;
+}
+
+void fuse_invalidate_attr(struct inode *inode)
+{
+       get_fuse_inode(inode)->i_time = jiffies - 1;
+}
+
+static void fuse_invalidate_entry(struct dentry *entry)
+{
+       d_invalidate(entry);
+       entry->d_time = jiffies - 1;
+}
+
+static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
+                           struct inode *dir, struct dentry *entry,
+                           int mode)
+{
+       struct fuse_entry_out outarg;
+       struct inode *inode;
+       struct fuse_inode *fi;
+       int err;
+
+       req->in.h.nodeid = get_node_id(dir);
+       req->inode = dir;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(outarg);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       if (err) {
+               fuse_put_request(fc, req);
+               return err;
+       }
+       inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
+                         &outarg.attr);
+       if (!inode) {
+               fuse_send_forget(fc, req, outarg.nodeid, 1);
+               return -ENOMEM;
+       }
+       fuse_put_request(fc, req);
+
+       /* Don't allow userspace to do really stupid things... */
+       if ((inode->i_mode ^ mode) & S_IFMT) {
+               iput(inode);
+               return -EIO;
+       }
+
+       entry->d_time = time_to_jiffies(outarg.entry_valid,
+                                       outarg.entry_valid_nsec);
+
+       fi = get_fuse_inode(inode);
+       fi->i_time = time_to_jiffies(outarg.attr_valid,
+                                    outarg.attr_valid_nsec);
+
+       d_instantiate(entry, inode);
+       fuse_invalidate_attr(dir);
+       return 0;
+}
+
+static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
+                     dev_t rdev)
+{
+       struct fuse_mknod_in inarg;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.mode = mode;
+       inarg.rdev = new_encode_dev(rdev);
+       req->in.h.opcode = FUSE_MKNOD;
+       req->in.numargs = 2;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = entry->d_name.len + 1;
+       req->in.args[1].value = entry->d_name.name;
+       return create_new_entry(fc, req, dir, entry, mode);
+}
+
+static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
+                      struct nameidata *nd)
+{
+       return fuse_mknod(dir, entry, mode, 0);
+}
+
+static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
+{
+       struct fuse_mkdir_in inarg;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.mode = mode;
+       req->in.h.opcode = FUSE_MKDIR;
+       req->in.numargs = 2;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = entry->d_name.len + 1;
+       req->in.args[1].value = entry->d_name.name;
+       return create_new_entry(fc, req, dir, entry, S_IFDIR);
+}
+
+static int fuse_symlink(struct inode *dir, struct dentry *entry,
+                       const char *link)
+{
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       unsigned len = strlen(link) + 1;
+       struct fuse_req *req;
+
+       if (len > FUSE_SYMLINK_MAX)
+               return -ENAMETOOLONG;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->in.h.opcode = FUSE_SYMLINK;
+       req->in.numargs = 2;
+       req->in.args[0].size = entry->d_name.len + 1;
+       req->in.args[0].value = entry->d_name.name;
+       req->in.args[1].size = len;
+       req->in.args[1].value = link;
+       return create_new_entry(fc, req, dir, entry, S_IFLNK);
+}
+
+static int fuse_unlink(struct inode *dir, struct dentry *entry)
+{
+       int err;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->in.h.opcode = FUSE_UNLINK;
+       req->in.h.nodeid = get_node_id(dir);
+       req->inode = dir;
+       req->in.numargs = 1;
+       req->in.args[0].size = entry->d_name.len + 1;
+       req->in.args[0].value = entry->d_name.name;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err) {
+               struct inode *inode = entry->d_inode;
+
+               /* Set nlink to zero so the inode can be cleared, if
+                   the inode does have more links this will be
+                   discovered at the next lookup/getattr */
+               inode->i_nlink = 0;
+               fuse_invalidate_attr(inode);
+               fuse_invalidate_attr(dir);
+       } else if (err == -EINTR)
+               fuse_invalidate_entry(entry);
+       return err;
+}
+
+static int fuse_rmdir(struct inode *dir, struct dentry *entry)
+{
+       int err;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->in.h.opcode = FUSE_RMDIR;
+       req->in.h.nodeid = get_node_id(dir);
+       req->inode = dir;
+       req->in.numargs = 1;
+       req->in.args[0].size = entry->d_name.len + 1;
+       req->in.args[0].value = entry->d_name.name;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err) {
+               entry->d_inode->i_nlink = 0;
+               fuse_invalidate_attr(dir);
+       } else if (err == -EINTR)
+               fuse_invalidate_entry(entry);
+       return err;
+}
+
+static int fuse_rename(struct inode *olddir, struct dentry *oldent,
+                      struct inode *newdir, struct dentry *newent)
+{
+       int err;
+       struct fuse_rename_in inarg;
+       struct fuse_conn *fc = get_fuse_conn(olddir);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.newdir = get_node_id(newdir);
+       req->in.h.opcode = FUSE_RENAME;
+       req->in.h.nodeid = get_node_id(olddir);
+       req->inode = olddir;
+       req->inode2 = newdir;
+       req->in.numargs = 3;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = oldent->d_name.len + 1;
+       req->in.args[1].value = oldent->d_name.name;
+       req->in.args[2].size = newent->d_name.len + 1;
+       req->in.args[2].value = newent->d_name.name;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err) {
+               fuse_invalidate_attr(olddir);
+               if (olddir != newdir)
+                       fuse_invalidate_attr(newdir);
+       } else if (err == -EINTR) {
+               /* If request was interrupted, DEITY only knows if the
+                  rename actually took place.  If the invalidation
+                  fails (e.g. some process has CWD under the renamed
+                  directory), then there can be inconsistency between
+                  the dcache and the real filesystem.  Tough luck. */
+               fuse_invalidate_entry(oldent);
+               if (newent->d_inode)
+                       fuse_invalidate_entry(newent);
+       }
+
+       return err;
+}
+
+static int fuse_link(struct dentry *entry, struct inode *newdir,
+                    struct dentry *newent)
+{
+       int err;
+       struct fuse_link_in inarg;
+       struct inode *inode = entry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.oldnodeid = get_node_id(inode);
+       req->in.h.opcode = FUSE_LINK;
+       req->inode2 = inode;
+       req->in.numargs = 2;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = newent->d_name.len + 1;
+       req->in.args[1].value = newent->d_name.name;
+       err = create_new_entry(fc, req, newdir, newent, inode->i_mode);
+       /* Contrary to "normal" filesystems it can happen that link
+          makes two "logical" inodes point to the same "physical"
+          inode.  We invalidate the attributes of the old one, so it
+          will reflect changes in the backing inode (link count,
+          etc.)
+       */
+       if (!err || err == -EINTR)
+               fuse_invalidate_attr(inode);
+       return err;
+}
+
+int fuse_do_getattr(struct inode *inode)
+{
+       int err;
+       struct fuse_attr_out arg;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->in.h.opcode = FUSE_GETATTR;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(arg);
+       req->out.args[0].value = &arg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err) {
+               if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) {
+                       make_bad_inode(inode);
+                       err = -EIO;
+               } else {
+                       struct fuse_inode *fi = get_fuse_inode(inode);
+                       fuse_change_attributes(inode, &arg.attr);
+                       fi->i_time = time_to_jiffies(arg.attr_valid,
+                                                    arg.attr_valid_nsec);
+               }
+       }
+       return err;
+}
+
+/*
+ * Calling into a user-controlled filesystem gives the filesystem
+ * daemon ptrace-like capabilities over the requester process.  This
+ * means, that the filesystem daemon is able to record the exact
+ * filesystem operations performed, and can also control the behavior
+ * of the requester process in otherwise impossible ways.  For example
+ * it can delay the operation for arbitrary length of time allowing
+ * DoS against the requester.
+ *
+ * For this reason only those processes can call into the filesystem,
+ * for which the owner of the mount has ptrace privilege.  This
+ * excludes processes started by other users, suid or sgid processes.
+ */
+static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
+{
+       if (fc->flags & FUSE_ALLOW_OTHER)
+               return 1;
+
+       if (task->euid == fc->user_id &&
+           task->suid == fc->user_id &&
+           task->uid == fc->user_id &&
+           task->egid == fc->group_id &&
+           task->sgid == fc->group_id &&
+           task->gid == fc->group_id)
+               return 1;
+
+       return 0;
+}
+
+static int fuse_revalidate(struct dentry *entry)
+{
+       struct inode *inode = entry->d_inode;
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       if (!fuse_allow_task(fc, current))
+               return -EACCES;
+       if (get_node_id(inode) != FUSE_ROOT_ID &&
+           time_before_eq(jiffies, fi->i_time))
+               return 0;
+
+       return fuse_do_getattr(inode);
+}
+
+static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       if (!fuse_allow_task(fc, current))
+               return -EACCES;
+       else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
+               int err = generic_permission(inode, mask, NULL);
+
+               /* If permission is denied, try to refresh file
+                  attributes.  This is also needed, because the root
+                  node will at first have no permissions */
+               if (err == -EACCES) {
+                       err = fuse_do_getattr(inode);
+                       if (!err)
+                               err = generic_permission(inode, mask, NULL);
+               }
+
+               /* FIXME: Need some mechanism to revoke permissions:
+                  currently if the filesystem suddenly changes the
+                  file mode, we will not be informed about it, and
+                  continue to allow access to the file/directory.
+
+                  This is actually not so grave, since the user can
+                  simply keep access to the file/directory anyway by
+                  keeping it open... */
+
+               return err;
+       } else {
+               int mode = inode->i_mode;
+               if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
+                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+                        return -EROFS;
+               if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
+                       return -EACCES;
+               return 0;
+       }
+}
+
+static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
+                        void *dstbuf, filldir_t filldir)
+{
+       while (nbytes >= FUSE_NAME_OFFSET) {
+               struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
+               size_t reclen = FUSE_DIRENT_SIZE(dirent);
+               int over;
+               if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
+                       return -EIO;
+               if (reclen > nbytes)
+                       break;
+
+               over = filldir(dstbuf, dirent->name, dirent->namelen,
+                              file->f_pos, dirent->ino, dirent->type);
+               if (over)
+                       break;
+
+               buf += reclen;
+               nbytes -= reclen;
+               file->f_pos = dirent->off;
+       }
+
+       return 0;
+}
+
+static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
+                                      struct inode *inode, loff_t pos,
+                                      size_t count)
+{
+       return fuse_send_read_common(req, file, inode, pos, count, 1);
+}
+
+static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
+{
+       int err;
+       size_t nbytes;
+       struct page *page;
+       struct inode *inode = file->f_dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       page = alloc_page(GFP_KERNEL);
+       if (!page) {
+               fuse_put_request(fc, req);
+               return -ENOMEM;
+       }
+       req->num_pages = 1;
+       req->pages[0] = page;
+       nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err)
+               err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
+                                   filldir);
+
+       __free_page(page);
+       fuse_invalidate_attr(inode); /* atime changed */
+       return err;
+}
+
+static char *read_link(struct dentry *dentry)
+{
+       struct inode *inode = dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req = fuse_get_request(fc);
+       char *link;
+
+       if (!req)
+               return ERR_PTR(-EINTR);
+
+       link = (char *) __get_free_page(GFP_KERNEL);
+       if (!link) {
+               link = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+       req->in.h.opcode = FUSE_READLINK;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->out.argvar = 1;
+       req->out.numargs = 1;
+       req->out.args[0].size = PAGE_SIZE - 1;
+       req->out.args[0].value = link;
+       request_send(fc, req);
+       if (req->out.h.error) {
+               free_page((unsigned long) link);
+               link = ERR_PTR(req->out.h.error);
+       } else
+               link[req->out.args[0].size] = '\0';
+ out:
+       fuse_put_request(fc, req);
+       fuse_invalidate_attr(inode); /* atime changed */
+       return link;
+}
+
+static void free_link(char *link)
+{
+       if (!IS_ERR(link))
+               free_page((unsigned long) link);
+}
+
+static void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       nd_set_link(nd, read_link(dentry));
+       return NULL;
+}
+
+static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
+{
+       free_link(nd_get_link(nd));
+}
+
+static int fuse_dir_open(struct inode *inode, struct file *file)
+{
+       return fuse_open_common(inode, file, 1);
+}
+
+static int fuse_dir_release(struct inode *inode, struct file *file)
+{
+       return fuse_release_common(inode, file, 1);
+}
+
+static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
+{
+       /* nfsd can call this with no file */
+       return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
+}
+
+static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
+{
+       unsigned ivalid = iattr->ia_valid;
+       unsigned fvalid = 0;
+
+       memset(fattr, 0, sizeof(*fattr));
+
+       if (ivalid & ATTR_MODE)
+               fvalid |= FATTR_MODE,   fattr->mode = iattr->ia_mode;
+       if (ivalid & ATTR_UID)
+               fvalid |= FATTR_UID,    fattr->uid = iattr->ia_uid;
+       if (ivalid & ATTR_GID)
+               fvalid |= FATTR_GID,    fattr->gid = iattr->ia_gid;
+       if (ivalid & ATTR_SIZE)
+               fvalid |= FATTR_SIZE,   fattr->size = iattr->ia_size;
+       /* You can only _set_ these together (they may change by themselves) */
+       if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
+               fvalid |= FATTR_ATIME | FATTR_MTIME;
+               fattr->atime = iattr->ia_atime.tv_sec;
+               fattr->mtime = iattr->ia_mtime.tv_sec;
+       }
+
+       return fvalid;
+}
+
+static int fuse_setattr(struct dentry *entry, struct iattr *attr)
+{
+       struct inode *inode = entry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_req *req;
+       struct fuse_setattr_in inarg;
+       struct fuse_attr_out outarg;
+       int err;
+       int is_truncate = 0;
+
+       if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
+               err = inode_change_ok(inode, attr);
+               if (err)
+                       return err;
+       }
+
+       if (attr->ia_valid & ATTR_SIZE) {
+               unsigned long limit;
+               is_truncate = 1;
+               limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+               if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
+                       send_sig(SIGXFSZ, current, 0);
+                       return -EFBIG;
+               }
+       }
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.valid = iattr_to_fattr(attr, &inarg.attr);
+       req->in.h.opcode = FUSE_SETATTR;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(outarg);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err) {
+               if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
+                       make_bad_inode(inode);
+                       err = -EIO;
+               } else {
+                       if (is_truncate) {
+                               loff_t origsize = i_size_read(inode);
+                               i_size_write(inode, outarg.attr.size);
+                               if (origsize > outarg.attr.size)
+                                       vmtruncate(inode, outarg.attr.size);
+                       }
+                       fuse_change_attributes(inode, &outarg.attr);
+                       fi->i_time = time_to_jiffies(outarg.attr_valid,
+                                                    outarg.attr_valid_nsec);
+               }
+       } else if (err == -EINTR)
+               fuse_invalidate_attr(inode);
+
+       return err;
+}
+
+static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
+                       struct kstat *stat)
+{
+       struct inode *inode = entry->d_inode;
+       int err = fuse_revalidate(entry);
+       if (!err)
+               generic_fillattr(inode, stat);
+
+       return err;
+}
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+                                 struct nameidata *nd)
+{
+       struct inode *inode;
+       int err = fuse_lookup_iget(dir, entry, &inode);
+       if (err)
+               return ERR_PTR(err);
+       if (inode && S_ISDIR(inode->i_mode)) {
+               /* Don't allow creating an alias to a directory  */
+               struct dentry *alias = d_find_alias(inode);
+               if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
+                       dput(alias);
+                       iput(inode);
+                       return ERR_PTR(-EIO);
+               }
+       }
+       return d_splice_alias(inode, entry);
+}
+
+static int fuse_setxattr(struct dentry *entry, const char *name,
+                        const void *value, size_t size, int flags)
+{
+       struct inode *inode = entry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_setxattr_in inarg;
+       int err;
+
+       if (size > FUSE_XATTR_SIZE_MAX)
+               return -E2BIG;
+
+       if (fc->no_setxattr)
+               return -EOPNOTSUPP;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.size = size;
+       inarg.flags = flags;
+       req->in.h.opcode = FUSE_SETXATTR;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 3;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = strlen(name) + 1;
+       req->in.args[1].value = name;
+       req->in.args[2].size = size;
+       req->in.args[2].value = value;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (err == -ENOSYS) {
+               fc->no_setxattr = 1;
+               err = -EOPNOTSUPP;
+       }
+       return err;
+}
+
+static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
+                            void *value, size_t size)
+{
+       struct inode *inode = entry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_getxattr_in inarg;
+       struct fuse_getxattr_out outarg;
+       ssize_t ret;
+
+       if (fc->no_getxattr)
+               return -EOPNOTSUPP;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.size = size;
+       req->in.h.opcode = FUSE_GETXATTR;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 2;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = strlen(name) + 1;
+       req->in.args[1].value = name;
+       /* This is really two different operations rolled into one */
+       req->out.numargs = 1;
+       if (size) {
+               req->out.argvar = 1;
+               req->out.args[0].size = size;
+               req->out.args[0].value = value;
+       } else {
+               req->out.args[0].size = sizeof(outarg);
+               req->out.args[0].value = &outarg;
+       }
+       request_send(fc, req);
+       ret = req->out.h.error;
+       if (!ret)
+               ret = size ? req->out.args[0].size : outarg.size;
+       else {
+               if (ret == -ENOSYS) {
+                       fc->no_getxattr = 1;
+                       ret = -EOPNOTSUPP;
+               }
+       }
+       fuse_put_request(fc, req);
+       return ret;
+}
+
+static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
+{
+       struct inode *inode = entry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_getxattr_in inarg;
+       struct fuse_getxattr_out outarg;
+       ssize_t ret;
+
+       if (fc->no_listxattr)
+               return -EOPNOTSUPP;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.size = size;
+       req->in.h.opcode = FUSE_LISTXATTR;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       /* This is really two different operations rolled into one */
+       req->out.numargs = 1;
+       if (size) {
+               req->out.argvar = 1;
+               req->out.args[0].size = size;
+               req->out.args[0].value = list;
+       } else {
+               req->out.args[0].size = sizeof(outarg);
+               req->out.args[0].value = &outarg;
+       }
+       request_send(fc, req);
+       ret = req->out.h.error;
+       if (!ret)
+               ret = size ? req->out.args[0].size : outarg.size;
+       else {
+               if (ret == -ENOSYS) {
+                       fc->no_listxattr = 1;
+                       ret = -EOPNOTSUPP;
+               }
+       }
+       fuse_put_request(fc, req);
+       return ret;
+}
+
+static int fuse_removexattr(struct dentry *entry, const char *name)
+{
+       struct inode *inode = entry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       int err;
+
+       if (fc->no_removexattr)
+               return -EOPNOTSUPP;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->in.h.opcode = FUSE_REMOVEXATTR;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 1;
+       req->in.args[0].size = strlen(name) + 1;
+       req->in.args[0].value = name;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (err == -ENOSYS) {
+               fc->no_removexattr = 1;
+               err = -EOPNOTSUPP;
+       }
+       return err;
+}
+
+static struct inode_operations fuse_dir_inode_operations = {
+       .lookup         = fuse_lookup,
+       .mkdir          = fuse_mkdir,
+       .symlink        = fuse_symlink,
+       .unlink         = fuse_unlink,
+       .rmdir          = fuse_rmdir,
+       .rename         = fuse_rename,
+       .link           = fuse_link,
+       .setattr        = fuse_setattr,
+       .create         = fuse_create,
+       .mknod          = fuse_mknod,
+       .permission     = fuse_permission,
+       .getattr        = fuse_getattr,
+       .setxattr       = fuse_setxattr,
+       .getxattr       = fuse_getxattr,
+       .listxattr      = fuse_listxattr,
+       .removexattr    = fuse_removexattr,
+};
+
+static struct file_operations fuse_dir_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .readdir        = fuse_readdir,
+       .open           = fuse_dir_open,
+       .release        = fuse_dir_release,
+       .fsync          = fuse_dir_fsync,
+};
+
+static struct inode_operations fuse_common_inode_operations = {
+       .setattr        = fuse_setattr,
+       .permission     = fuse_permission,
+       .getattr        = fuse_getattr,
+       .setxattr       = fuse_setxattr,
+       .getxattr       = fuse_getxattr,
+       .listxattr      = fuse_listxattr,
+       .removexattr    = fuse_removexattr,
+};
+
+static struct inode_operations fuse_symlink_inode_operations = {
+       .setattr        = fuse_setattr,
+       .follow_link    = fuse_follow_link,
+       .put_link       = fuse_put_link,
+       .readlink       = generic_readlink,
+       .getattr        = fuse_getattr,
+       .setxattr       = fuse_setxattr,
+       .getxattr       = fuse_getxattr,
+       .listxattr      = fuse_listxattr,
+       .removexattr    = fuse_removexattr,
+};
+
+void fuse_init_common(struct inode *inode)
+{
+       inode->i_op = &fuse_common_inode_operations;
+}
+
+void fuse_init_dir(struct inode *inode)
+{
+       inode->i_op = &fuse_dir_inode_operations;
+       inode->i_fop = &fuse_dir_operations;
+}
+
+void fuse_init_symlink(struct inode *inode)
+{
+       inode->i_op = &fuse_symlink_inode_operations;
+}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
new file mode 100644 (file)
index 0000000..6454022
--- /dev/null
@@ -0,0 +1,555 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+
+static struct file_operations fuse_direct_io_file_operations;
+
+int fuse_open_common(struct inode *inode, struct file *file, int isdir)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req;
+       struct fuse_open_in inarg;
+       struct fuse_open_out outarg;
+       struct fuse_file *ff;
+       int err;
+
+       err = generic_file_open(inode, file);
+       if (err)
+               return err;
+
+       /* If opening the root node, no lookup has been performed on
+          it, so the attributes must be refreshed */
+       if (get_node_id(inode) == FUSE_ROOT_ID) {
+               int err = fuse_do_getattr(inode);
+               if (err)
+                       return err;
+       }
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       err = -ENOMEM;
+       ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
+       if (!ff)
+               goto out_put_request;
+
+       ff->release_req = fuse_request_alloc();
+       if (!ff->release_req) {
+               kfree(ff);
+               goto out_put_request;
+       }
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+       req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(outarg);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       if (err) {
+               fuse_request_free(ff->release_req);
+               kfree(ff);
+       } else {
+               if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO))
+                       file->f_op = &fuse_direct_io_file_operations;
+               if (!(outarg.open_flags & FOPEN_KEEP_CACHE))
+                       invalidate_inode_pages(inode->i_mapping);
+               ff->fh = outarg.fh;
+               file->private_data = ff;
+       }
+
+ out_put_request:
+       fuse_put_request(fc, req);
+       return err;
+}
+
+int fuse_release_common(struct inode *inode, struct file *file, int isdir)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_file *ff = file->private_data;
+       struct fuse_req *req = ff->release_req;
+       struct fuse_release_in *inarg = &req->misc.release_in;
+
+       inarg->fh = ff->fh;
+       inarg->flags = file->f_flags & ~O_EXCL;
+       req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(struct fuse_release_in);
+       req->in.args[0].value = inarg;
+       request_send_background(fc, req);
+       kfree(ff);
+
+       /* Return value is ignored by VFS */
+       return 0;
+}
+
+static int fuse_open(struct inode *inode, struct file *file)
+{
+       return fuse_open_common(inode, file, 0);
+}
+
+static int fuse_release(struct inode *inode, struct file *file)
+{
+       return fuse_release_common(inode, file, 0);
+}
+
+static int fuse_flush(struct file *file)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_file *ff = file->private_data;
+       struct fuse_req *req;
+       struct fuse_flush_in inarg;
+       int err;
+
+       if (fc->no_flush)
+               return 0;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.fh = ff->fh;
+       req->in.h.opcode = FUSE_FLUSH;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->file = file;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (err == -ENOSYS) {
+               fc->no_flush = 1;
+               err = 0;
+       }
+       return err;
+}
+
+int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+                     int isdir)
+{
+       struct inode *inode = de->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_file *ff = file->private_data;
+       struct fuse_req *req;
+       struct fuse_fsync_in inarg;
+       int err;
+
+       if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
+               return 0;
+
+       req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       memset(&inarg, 0, sizeof(inarg));
+       inarg.fh = ff->fh;
+       inarg.fsync_flags = datasync ? 1 : 0;
+       req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->file = file;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].value = &inarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (err == -ENOSYS) {
+               if (isdir)
+                       fc->no_fsyncdir = 1;
+               else
+                       fc->no_fsync = 1;
+               err = 0;
+       }
+       return err;
+}
+
+static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+{
+       return fuse_fsync_common(file, de, datasync, 0);
+}
+
+size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
+                            struct inode *inode, loff_t pos, size_t count,
+                            int isdir)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_file *ff = file->private_data;
+       struct fuse_read_in inarg;
+
+       memset(&inarg, 0, sizeof(struct fuse_read_in));
+       inarg.fh = ff->fh;
+       inarg.offset = pos;
+       inarg.size = count;
+       req->in.h.opcode = isdir ? FUSE_READDIR : FUSE_READ;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->file = file;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(struct fuse_read_in);
+       req->in.args[0].value = &inarg;
+       req->out.argpages = 1;
+       req->out.argvar = 1;
+       req->out.numargs = 1;
+       req->out.args[0].size = count;
+       request_send(fc, req);
+       return req->out.args[0].size;
+}
+
+static inline size_t fuse_send_read(struct fuse_req *req, struct file *file,
+                                   struct inode *inode, loff_t pos,
+                                   size_t count)
+{
+       return fuse_send_read_common(req, file, inode, pos, count, 0);
+}
+
+static int fuse_readpage(struct file *file, struct page *page)
+{
+       struct inode *inode = page->mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT;
+       struct fuse_req *req = fuse_get_request(fc);
+       int err = -EINTR;
+       if (!req)
+               goto out;
+
+       req->out.page_zeroing = 1;
+       req->num_pages = 1;
+       req->pages[0] = page;
+       fuse_send_read(req, file, inode, pos, PAGE_CACHE_SIZE);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err)
+               SetPageUptodate(page);
+       fuse_invalidate_attr(inode); /* atime changed */
+ out:
+       unlock_page(page);
+       return err;
+}
+
+static int fuse_send_readpages(struct fuse_req *req, struct file *file,
+                              struct inode *inode)
+{
+       loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT;
+       size_t count = req->num_pages << PAGE_CACHE_SHIFT;
+       unsigned i;
+       req->out.page_zeroing = 1;
+       fuse_send_read(req, file, inode, pos, count);
+       for (i = 0; i < req->num_pages; i++) {
+               struct page *page = req->pages[i];
+               if (!req->out.h.error)
+                       SetPageUptodate(page);
+               unlock_page(page);
+       }
+       return req->out.h.error;
+}
+
+struct fuse_readpages_data {
+       struct fuse_req *req;
+       struct file *file;
+       struct inode *inode;
+};
+
+static int fuse_readpages_fill(void *_data, struct page *page)
+{
+       struct fuse_readpages_data *data = _data;
+       struct fuse_req *req = data->req;
+       struct inode *inode = data->inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       if (req->num_pages &&
+           (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
+            (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
+            req->pages[req->num_pages - 1]->index + 1 != page->index)) {
+               int err = fuse_send_readpages(req, data->file, inode);
+               if (err) {
+                       unlock_page(page);
+                       return err;
+               }
+               fuse_reset_request(req);
+       }
+       req->pages[req->num_pages] = page;
+       req->num_pages ++;
+       return 0;
+}
+
+static int fuse_readpages(struct file *file, struct address_space *mapping,
+                         struct list_head *pages, unsigned nr_pages)
+{
+       struct inode *inode = mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_readpages_data data;
+       int err;
+       data.file = file;
+       data.inode = inode;
+       data.req = fuse_get_request(fc);
+       if (!data.req)
+               return -EINTR;
+
+       err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
+       if (!err && data.req->num_pages)
+               err = fuse_send_readpages(data.req, file, inode);
+       fuse_put_request(fc, data.req);
+       fuse_invalidate_attr(inode); /* atime changed */
+       return err;
+}
+
+static size_t fuse_send_write(struct fuse_req *req, struct file *file,
+                             struct inode *inode, loff_t pos, size_t count)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_file *ff = file->private_data;
+       struct fuse_write_in inarg;
+       struct fuse_write_out outarg;
+
+       memset(&inarg, 0, sizeof(struct fuse_write_in));
+       inarg.fh = ff->fh;
+       inarg.offset = pos;
+       inarg.size = count;
+       req->in.h.opcode = FUSE_WRITE;
+       req->in.h.nodeid = get_node_id(inode);
+       req->inode = inode;
+       req->file = file;
+       req->in.argpages = 1;
+       req->in.numargs = 2;
+       req->in.args[0].size = sizeof(struct fuse_write_in);
+       req->in.args[0].value = &inarg;
+       req->in.args[1].size = count;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(struct fuse_write_out);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       return outarg.size;
+}
+
+static int fuse_prepare_write(struct file *file, struct page *page,
+                             unsigned offset, unsigned to)
+{
+       /* No op */
+       return 0;
+}
+
+static int fuse_commit_write(struct file *file, struct page *page,
+                            unsigned offset, unsigned to)
+{
+       int err;
+       size_t nres;
+       unsigned count = to - offset;
+       struct inode *inode = page->mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->num_pages = 1;
+       req->pages[0] = page;
+       req->page_offset = offset;
+       nres = fuse_send_write(req, file, inode, pos, count);
+       err = req->out.h.error;
+       fuse_put_request(fc, req);
+       if (!err && nres != count)
+               err = -EIO;
+       if (!err) {
+               pos += count;
+               if (pos > i_size_read(inode))
+                       i_size_write(inode, pos);
+
+               if (offset == 0 && to == PAGE_CACHE_SIZE) {
+                       clear_page_dirty(page);
+                       SetPageUptodate(page);
+               }
+       }
+       fuse_invalidate_attr(inode);
+       return err;
+}
+
+static void fuse_release_user_pages(struct fuse_req *req, int write)
+{
+       unsigned i;
+
+       for (i = 0; i < req->num_pages; i++) {
+               struct page *page = req->pages[i];
+               if (write)
+                       set_page_dirty_lock(page);
+               put_page(page);
+       }
+}
+
+static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
+                              unsigned nbytes, int write)
+{
+       unsigned long user_addr = (unsigned long) buf;
+       unsigned offset = user_addr & ~PAGE_MASK;
+       int npages;
+
+       /* This doesn't work with nfsd */
+       if (!current->mm)
+               return -EPERM;
+
+       nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
+       npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       npages = min(npages, FUSE_MAX_PAGES_PER_REQ);
+       down_read(&current->mm->mmap_sem);
+       npages = get_user_pages(current, current->mm, user_addr, npages, write,
+                               0, req->pages, NULL);
+       up_read(&current->mm->mmap_sem);
+       if (npages < 0)
+               return npages;
+
+       req->num_pages = npages;
+       req->page_offset = offset;
+       return 0;
+}
+
+static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
+                             size_t count, loff_t *ppos, int write)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       size_t nmax = write ? fc->max_write : fc->max_read;
+       loff_t pos = *ppos;
+       ssize_t res = 0;
+       struct fuse_req *req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       while (count) {
+               size_t tmp;
+               size_t nres;
+               size_t nbytes = min(count, nmax);
+               int err = fuse_get_user_pages(req, buf, nbytes, !write);
+               if (err) {
+                       res = err;
+                       break;
+               }
+               tmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
+               nbytes = min(nbytes, tmp);
+               if (write)
+                       nres = fuse_send_write(req, file, inode, pos, nbytes);
+               else
+                       nres = fuse_send_read(req, file, inode, pos, nbytes);
+               fuse_release_user_pages(req, !write);
+               if (req->out.h.error) {
+                       if (!res)
+                               res = req->out.h.error;
+                       break;
+               } else if (nres > nbytes) {
+                       res = -EIO;
+                       break;
+               }
+               count -= nres;
+               res += nres;
+               pos += nres;
+               buf += nres;
+               if (nres != nbytes)
+                       break;
+               if (count)
+                       fuse_reset_request(req);
+       }
+       fuse_put_request(fc, req);
+       if (res > 0) {
+               if (write && pos > i_size_read(inode))
+                       i_size_write(inode, pos);
+               *ppos = pos;
+       }
+       fuse_invalidate_attr(inode);
+
+       return res;
+}
+
+static ssize_t fuse_direct_read(struct file *file, char __user *buf,
+                                    size_t count, loff_t *ppos)
+{
+       return fuse_direct_io(file, buf, count, ppos, 0);
+}
+
+static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       struct inode *inode = file->f_dentry->d_inode;
+       ssize_t res;
+       /* Don't allow parallel writes to the same file */
+       down(&inode->i_sem);
+       res = fuse_direct_io(file, buf, count, ppos, 1);
+       up(&inode->i_sem);
+       return res;
+}
+
+static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       if ((vma->vm_flags & VM_SHARED)) {
+               if ((vma->vm_flags & VM_WRITE))
+                       return -ENODEV;
+               else
+                       vma->vm_flags &= ~VM_MAYWRITE;
+       }
+       return generic_file_mmap(file, vma);
+}
+
+static int fuse_set_page_dirty(struct page *page)
+{
+       printk("fuse_set_page_dirty: should not happen\n");
+       dump_stack();
+       return 0;
+}
+
+static struct file_operations fuse_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_file_read,
+       .write          = generic_file_write,
+       .mmap           = fuse_file_mmap,
+       .open           = fuse_open,
+       .flush          = fuse_flush,
+       .release        = fuse_release,
+       .fsync          = fuse_fsync,
+       .sendfile       = generic_file_sendfile,
+};
+
+static struct file_operations fuse_direct_io_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = fuse_direct_read,
+       .write          = fuse_direct_write,
+       .open           = fuse_open,
+       .flush          = fuse_flush,
+       .release        = fuse_release,
+       .fsync          = fuse_fsync,
+       /* no mmap and sendfile */
+};
+
+static struct address_space_operations fuse_file_aops  = {
+       .readpage       = fuse_readpage,
+       .prepare_write  = fuse_prepare_write,
+       .commit_write   = fuse_commit_write,
+       .readpages      = fuse_readpages,
+       .set_page_dirty = fuse_set_page_dirty,
+};
+
+void fuse_init_file_inode(struct inode *inode)
+{
+       inode->i_fop = &fuse_file_operations;
+       inode->i_data.a_ops = &fuse_file_aops;
+}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
new file mode 100644 (file)
index 0000000..24d7615
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include <linux/fuse.h>
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/backing-dev.h>
+#include <asm/semaphore.h>
+
+/** Max number of pages that can be used in a single read request */
+#define FUSE_MAX_PAGES_PER_REQ 32
+
+/** If more requests are outstanding, then the operation will block */
+#define FUSE_MAX_OUTSTANDING 10
+
+/** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem
+    module will check permissions based on the file mode.  Otherwise no
+    permission checking is done in the kernel */
+#define FUSE_DEFAULT_PERMISSIONS (1 << 0)
+
+/** If the FUSE_ALLOW_OTHER flag is given, then not only the user
+    doing the mount will be allowed to access the filesystem */
+#define FUSE_ALLOW_OTHER         (1 << 1)
+
+
+/** FUSE inode */
+struct fuse_inode {
+       /** Inode data */
+       struct inode inode;
+
+       /** Unique ID, which identifies the inode between userspace
+        * and kernel */
+       u64 nodeid;
+
+       /** Number of lookups on this inode */
+       u64 nlookup;
+
+       /** The request used for sending the FORGET message */
+       struct fuse_req *forget_req;
+
+       /** Time in jiffies until the file attributes are valid */
+       unsigned long i_time;
+};
+
+/** FUSE specific file data */
+struct fuse_file {
+       /** Request reserved for flush and release */
+       struct fuse_req *release_req;
+
+       /** File handle used by userspace */
+       u64 fh;
+};
+
+/** One input argument of a request */
+struct fuse_in_arg {
+       unsigned size;
+       const void *value;
+};
+
+/** The request input */
+struct fuse_in {
+       /** The request header */
+       struct fuse_in_header h;
+
+       /** True if the data for the last argument is in req->pages */
+       unsigned argpages:1;
+
+       /** Number of arguments */
+       unsigned numargs;
+
+       /** Array of arguments */
+       struct fuse_in_arg args[3];
+};
+
+/** One output argument of a request */
+struct fuse_arg {
+       unsigned size;
+       void *value;
+};
+
+/** The request output */
+struct fuse_out {
+       /** Header returned from userspace */
+       struct fuse_out_header h;
+
+       /** Last argument is variable length (can be shorter than
+           arg->size) */
+       unsigned argvar:1;
+
+       /** Last argument is a list of pages to copy data to */
+       unsigned argpages:1;
+
+       /** Zero partially or not copied pages */
+       unsigned page_zeroing:1;
+
+       /** Number or arguments */
+       unsigned numargs;
+
+       /** Array of arguments */
+       struct fuse_arg args[3];
+};
+
+struct fuse_req;
+struct fuse_conn;
+
+/**
+ * A request to the client
+ */
+struct fuse_req {
+       /** This can be on either unused_list, pending or processing
+           lists in fuse_conn */
+       struct list_head list;
+
+       /** Entry on the background list */
+       struct list_head bg_entry;
+
+       /** refcount */
+       atomic_t count;
+
+       /** True if the request has reply */
+       unsigned isreply:1;
+
+       /** The request is preallocated */
+       unsigned preallocated:1;
+
+       /** The request was interrupted */
+       unsigned interrupted:1;
+
+       /** Request is sent in the background */
+       unsigned background:1;
+
+       /** Data is being copied to/from the request */
+       unsigned locked:1;
+
+       /** Request has been sent to userspace */
+       unsigned sent:1;
+
+       /** The request is finished */
+       unsigned finished:1;
+
+       /** The request input */
+       struct fuse_in in;
+
+       /** The request output */
+       struct fuse_out out;
+
+       /** Used to wake up the task waiting for completion of request*/
+       wait_queue_head_t waitq;
+
+       /** Data for asynchronous requests */
+       union {
+               struct fuse_forget_in forget_in;
+               struct fuse_release_in release_in;
+               struct fuse_init_in_out init_in_out;
+       } misc;
+
+       /** page vector */
+       struct page *pages[FUSE_MAX_PAGES_PER_REQ];
+
+       /** number of pages in vector */
+       unsigned num_pages;
+
+       /** offset of data on first page */
+       unsigned page_offset;
+
+       /** Inode used in the request */
+       struct inode *inode;
+
+       /** Second inode used in the request (or NULL) */
+       struct inode *inode2;
+
+       /** File used in the request (or NULL) */
+       struct file *file;
+};
+
+/**
+ * A Fuse connection.
+ *
+ * This structure is created, when the filesystem is mounted, and is
+ * destroyed, when the client device is closed and the filesystem is
+ * unmounted.
+ */
+struct fuse_conn {
+       /** Reference count */
+       int count;
+
+       /** The user id for this mount */
+       uid_t user_id;
+
+       /** The group id for this mount */
+       gid_t group_id;
+
+       /** The fuse mount flags for this mount */
+       unsigned flags;
+
+       /** Maximum read size */
+       unsigned max_read;
+
+       /** Maximum write size */
+       unsigned max_write;
+
+       /** Readers of the connection are waiting on this */
+       wait_queue_head_t waitq;
+
+       /** The list of pending requests */
+       struct list_head pending;
+
+       /** The list of requests being processed */
+       struct list_head processing;
+
+       /** Requests put in the background (RELEASE or any other
+           interrupted request) */
+       struct list_head background;
+
+       /** Controls the maximum number of outstanding requests */
+       struct semaphore outstanding_sem;
+
+       /** This counts the number of outstanding requests if
+           outstanding_sem would go negative */
+       unsigned outstanding_debt;
+
+       /** RW semaphore for exclusion with fuse_put_super() */
+       struct rw_semaphore sbput_sem;
+
+       /** The list of unused requests */
+       struct list_head unused_list;
+
+       /** The next unique request id */
+       u64 reqctr;
+
+       /** Mount is active */
+       unsigned mounted : 1;
+
+       /** Connection established */
+       unsigned connected : 1;
+
+       /** Connection failed (version mismatch) */
+       unsigned conn_error : 1;
+
+       /** Is fsync not implemented by fs? */
+       unsigned no_fsync : 1;
+
+       /** Is fsyncdir not implemented by fs? */
+       unsigned no_fsyncdir : 1;
+
+       /** Is flush not implemented by fs? */
+       unsigned no_flush : 1;
+
+       /** Is setxattr not implemented by fs? */
+       unsigned no_setxattr : 1;
+
+       /** Is getxattr not implemented by fs? */
+       unsigned no_getxattr : 1;
+
+       /** Is listxattr not implemented by fs? */
+       unsigned no_listxattr : 1;
+
+       /** Is removexattr not implemented by fs? */
+       unsigned no_removexattr : 1;
+
+       /** Backing dev info */
+       struct backing_dev_info bdi;
+};
+
+static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb)
+{
+       return (struct fuse_conn **) &sb->s_fs_info;
+}
+
+static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
+{
+       return *get_fuse_conn_super_p(sb);
+}
+
+static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
+{
+       return get_fuse_conn_super(inode->i_sb);
+}
+
+static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
+{
+       return container_of(inode, struct fuse_inode, inode);
+}
+
+static inline u64 get_node_id(struct inode *inode)
+{
+       return get_fuse_inode(inode)->nodeid;
+}
+
+/** Device operations */
+extern struct file_operations fuse_dev_operations;
+
+/**
+ * This is the single global spinlock which protects FUSE's structures
+ *
+ * The following data is protected by this lock:
+ *
+ *  - the private_data field of the device file
+ *  - the s_fs_info field of the super block
+ *  - unused_list, pending, processing lists in fuse_conn
+ *  - background list in fuse_conn
+ *  - the unique request ID counter reqctr in fuse_conn
+ *  - the sb (super_block) field in fuse_conn
+ *  - the file (device file) field in fuse_conn
+ */
+extern spinlock_t fuse_lock;
+
+/**
+ * Get a filled in inode
+ */
+struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+                       int generation, struct fuse_attr *attr);
+
+/**
+ * Send FORGET command
+ */
+void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
+                     unsigned long nodeid, u64 nlookup);
+
+/**
+ * Send READ or READDIR request
+ */
+size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
+                            struct inode *inode, loff_t pos, size_t count,
+                            int isdir);
+
+/**
+ * Send OPEN or OPENDIR request
+ */
+int fuse_open_common(struct inode *inode, struct file *file, int isdir);
+
+/**
+ * Send RELEASE or RELEASEDIR request
+ */
+int fuse_release_common(struct inode *inode, struct file *file, int isdir);
+
+/**
+ * Send FSYNC or FSYNCDIR request
+ */
+int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+                     int isdir);
+
+/**
+ * Initialise file operations on a regular file
+ */
+void fuse_init_file_inode(struct inode *inode);
+
+/**
+ * Initialise inode operations on regular files and special files
+ */
+void fuse_init_common(struct inode *inode);
+
+/**
+ * Initialise inode and file operations on a directory
+ */
+void fuse_init_dir(struct inode *inode);
+
+/**
+ * Initialise inode operations on a symlink
+ */
+void fuse_init_symlink(struct inode *inode);
+
+/**
+ * Change attributes of an inode
+ */
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr);
+
+/**
+ * Check if the connection can be released, and if yes, then free the
+ * connection structure
+ */
+void fuse_release_conn(struct fuse_conn *fc);
+
+/**
+ * Initialize the client device
+ */
+int fuse_dev_init(void);
+
+/**
+ * Cleanup the client device
+ */
+void fuse_dev_cleanup(void);
+
+/**
+ * Allocate a request
+ */
+struct fuse_req *fuse_request_alloc(void);
+
+/**
+ * Free a request
+ */
+void fuse_request_free(struct fuse_req *req);
+
+/**
+ * Reinitialize a request, the preallocated flag is left unmodified
+ */
+void fuse_reset_request(struct fuse_req *req);
+
+/**
+ * Reserve a preallocated request
+ */
+struct fuse_req *fuse_get_request(struct fuse_conn *fc);
+
+/**
+ * Decrement reference count of a request.  If count goes to zero put
+ * on unused list (preallocated) or free reqest (not preallocated).
+ */
+void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Send a request (synchronous)
+ */
+void request_send(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Send a request with no reply
+ */
+void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Send a request in the background
+ */
+void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
+
+/**
+ * Release inodes and file assiciated with background request
+ */
+void fuse_release_background(struct fuse_req *req);
+
+/**
+ * Get the attributes of a file
+ */
+int fuse_do_getattr(struct inode *inode);
+
+/**
+ * Invalidate inode attributes
+ */
+void fuse_invalidate_attr(struct inode *inode);
+
+/**
+ * Send the INIT message
+ */
+void fuse_send_init(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
new file mode 100644 (file)
index 0000000..e69a546
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/parser.h>
+#include <linux/statfs.h>
+
+MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
+MODULE_DESCRIPTION("Filesystem in Userspace");
+MODULE_LICENSE("GPL");
+
+spinlock_t fuse_lock;
+static kmem_cache_t *fuse_inode_cachep;
+
+#define FUSE_SUPER_MAGIC 0x65735546
+
+struct fuse_mount_data {
+       int fd;
+       unsigned rootmode;
+       unsigned user_id;
+       unsigned group_id;
+       unsigned fd_present : 1;
+       unsigned rootmode_present : 1;
+       unsigned user_id_present : 1;
+       unsigned group_id_present : 1;
+       unsigned flags;
+       unsigned max_read;
+};
+
+static struct inode *fuse_alloc_inode(struct super_block *sb)
+{
+       struct inode *inode;
+       struct fuse_inode *fi;
+
+       inode = kmem_cache_alloc(fuse_inode_cachep, SLAB_KERNEL);
+       if (!inode)
+               return NULL;
+
+       fi = get_fuse_inode(inode);
+       fi->i_time = jiffies - 1;
+       fi->nodeid = 0;
+       fi->nlookup = 0;
+       fi->forget_req = fuse_request_alloc();
+       if (!fi->forget_req) {
+               kmem_cache_free(fuse_inode_cachep, inode);
+               return NULL;
+       }
+
+       return inode;
+}
+
+static void fuse_destroy_inode(struct inode *inode)
+{
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       if (fi->forget_req)
+               fuse_request_free(fi->forget_req);
+       kmem_cache_free(fuse_inode_cachep, inode);
+}
+
+static void fuse_read_inode(struct inode *inode)
+{
+       /* No op */
+}
+
+void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
+                     unsigned long nodeid, u64 nlookup)
+{
+       struct fuse_forget_in *inarg = &req->misc.forget_in;
+       inarg->nlookup = nlookup;
+       req->in.h.opcode = FUSE_FORGET;
+       req->in.h.nodeid = nodeid;
+       req->in.numargs = 1;
+       req->in.args[0].size = sizeof(struct fuse_forget_in);
+       req->in.args[0].value = inarg;
+       request_send_noreply(fc, req);
+}
+
+static void fuse_clear_inode(struct inode *inode)
+{
+       if (inode->i_sb->s_flags & MS_ACTIVE) {
+               struct fuse_conn *fc = get_fuse_conn(inode);
+               struct fuse_inode *fi = get_fuse_inode(inode);
+               fuse_send_forget(fc, fi->forget_req, fi->nodeid, fi->nlookup);
+               fi->forget_req = NULL;
+       }
+}
+
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
+{
+       if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
+               invalidate_inode_pages(inode->i_mapping);
+
+       inode->i_ino     = attr->ino;
+       inode->i_mode    = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
+       inode->i_nlink   = attr->nlink;
+       inode->i_uid     = attr->uid;
+       inode->i_gid     = attr->gid;
+       i_size_write(inode, attr->size);
+       inode->i_blksize = PAGE_CACHE_SIZE;
+       inode->i_blocks  = attr->blocks;
+       inode->i_atime.tv_sec   = attr->atime;
+       inode->i_atime.tv_nsec  = attr->atimensec;
+       inode->i_mtime.tv_sec   = attr->mtime;
+       inode->i_mtime.tv_nsec  = attr->mtimensec;
+       inode->i_ctime.tv_sec   = attr->ctime;
+       inode->i_ctime.tv_nsec  = attr->ctimensec;
+}
+
+static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
+{
+       inode->i_mode = attr->mode & S_IFMT;
+       i_size_write(inode, attr->size);
+       if (S_ISREG(inode->i_mode)) {
+               fuse_init_common(inode);
+               fuse_init_file_inode(inode);
+       } else if (S_ISDIR(inode->i_mode))
+               fuse_init_dir(inode);
+       else if (S_ISLNK(inode->i_mode))
+               fuse_init_symlink(inode);
+       else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
+                S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+               fuse_init_common(inode);
+               init_special_inode(inode, inode->i_mode,
+                                  new_decode_dev(attr->rdev));
+       } else {
+               /* Don't let user create weird files */
+               inode->i_mode = S_IFREG;
+               fuse_init_common(inode);
+               fuse_init_file_inode(inode);
+       }
+}
+
+static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
+{
+       unsigned long nodeid = *(unsigned long *) _nodeidp;
+       if (get_node_id(inode) == nodeid)
+               return 1;
+       else
+               return 0;
+}
+
+static int fuse_inode_set(struct inode *inode, void *_nodeidp)
+{
+       unsigned long nodeid = *(unsigned long *) _nodeidp;
+       get_fuse_inode(inode)->nodeid = nodeid;
+       return 0;
+}
+
+struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+                       int generation, struct fuse_attr *attr)
+{
+       struct inode *inode;
+       struct fuse_inode *fi;
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
+       int retried = 0;
+
+ retry:
+       inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
+       if (!inode)
+               return NULL;
+
+       if ((inode->i_state & I_NEW)) {
+               inode->i_flags |= S_NOATIME|S_NOCMTIME;
+               inode->i_generation = generation;
+               inode->i_data.backing_dev_info = &fc->bdi;
+               fuse_init_inode(inode, attr);
+               unlock_new_inode(inode);
+       } else if ((inode->i_mode ^ attr->mode) & S_IFMT) {
+               BUG_ON(retried);
+               /* Inode has changed type, any I/O on the old should fail */
+               make_bad_inode(inode);
+               iput(inode);
+               retried = 1;
+               goto retry;
+       }
+
+       fi = get_fuse_inode(inode);
+       fi->nlookup ++;
+       fuse_change_attributes(inode, attr);
+       return inode;
+}
+
+static void fuse_put_super(struct super_block *sb)
+{
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
+
+       down_write(&fc->sbput_sem);
+       while (!list_empty(&fc->background))
+               fuse_release_background(list_entry(fc->background.next,
+                                                  struct fuse_req, bg_entry));
+
+       spin_lock(&fuse_lock);
+       fc->mounted = 0;
+       fc->user_id = 0;
+       fc->group_id = 0;
+       fc->flags = 0;
+       /* Flush all readers on this fs */
+       wake_up_all(&fc->waitq);
+       up_write(&fc->sbput_sem);
+       fuse_release_conn(fc);
+       spin_unlock(&fuse_lock);
+}
+
+static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
+{
+       stbuf->f_type    = FUSE_SUPER_MAGIC;
+       stbuf->f_bsize   = attr->bsize;
+       stbuf->f_blocks  = attr->blocks;
+       stbuf->f_bfree   = attr->bfree;
+       stbuf->f_bavail  = attr->bavail;
+       stbuf->f_files   = attr->files;
+       stbuf->f_ffree   = attr->ffree;
+       stbuf->f_namelen = attr->namelen;
+       /* fsid is left zero */
+}
+
+static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
+       struct fuse_req *req;
+       struct fuse_statfs_out outarg;
+       int err;
+
+        req = fuse_get_request(fc);
+       if (!req)
+               return -EINTR;
+
+       req->in.numargs = 0;
+       req->in.h.opcode = FUSE_STATFS;
+       req->out.numargs = 1;
+       req->out.args[0].size = sizeof(outarg);
+       req->out.args[0].value = &outarg;
+       request_send(fc, req);
+       err = req->out.h.error;
+       if (!err)
+               convert_fuse_statfs(buf, &outarg.st);
+       fuse_put_request(fc, req);
+       return err;
+}
+
+enum {
+       OPT_FD,
+       OPT_ROOTMODE,
+       OPT_USER_ID,
+       OPT_GROUP_ID,
+       OPT_DEFAULT_PERMISSIONS,
+       OPT_ALLOW_OTHER,
+       OPT_MAX_READ,
+       OPT_ERR
+};
+
+static match_table_t tokens = {
+       {OPT_FD,                        "fd=%u"},
+       {OPT_ROOTMODE,                  "rootmode=%o"},
+       {OPT_USER_ID,                   "user_id=%u"},
+       {OPT_GROUP_ID,                  "group_id=%u"},
+       {OPT_DEFAULT_PERMISSIONS,       "default_permissions"},
+       {OPT_ALLOW_OTHER,               "allow_other"},
+       {OPT_MAX_READ,                  "max_read=%u"},
+       {OPT_ERR,                       NULL}
+};
+
+static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
+{
+       char *p;
+       memset(d, 0, sizeof(struct fuse_mount_data));
+       d->max_read = ~0;
+
+       while ((p = strsep(&opt, ",")) != NULL) {
+               int token;
+               int value;
+               substring_t args[MAX_OPT_ARGS];
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case OPT_FD:
+                       if (match_int(&args[0], &value))
+                               return 0;
+                       d->fd = value;
+                       d->fd_present = 1;
+                       break;
+
+               case OPT_ROOTMODE:
+                       if (match_octal(&args[0], &value))
+                               return 0;
+                       d->rootmode = value;
+                       d->rootmode_present = 1;
+                       break;
+
+               case OPT_USER_ID:
+                       if (match_int(&args[0], &value))
+                               return 0;
+                       d->user_id = value;
+                       d->user_id_present = 1;
+                       break;
+
+               case OPT_GROUP_ID:
+                       if (match_int(&args[0], &value))
+                               return 0;
+                       d->group_id = value;
+                       d->group_id_present = 1;
+                       break;
+
+               case OPT_DEFAULT_PERMISSIONS:
+                       d->flags |= FUSE_DEFAULT_PERMISSIONS;
+                       break;
+
+               case OPT_ALLOW_OTHER:
+                       d->flags |= FUSE_ALLOW_OTHER;
+                       break;
+
+               case OPT_MAX_READ:
+                       if (match_int(&args[0], &value))
+                               return 0;
+                       d->max_read = value;
+                       break;
+
+               default:
+                       return 0;
+               }
+       }
+
+       if (!d->fd_present || !d->rootmode_present ||
+           !d->user_id_present || !d->group_id_present)
+               return 0;
+
+       return 1;
+}
+
+static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+       struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);
+
+       seq_printf(m, ",user_id=%u", fc->user_id);
+       seq_printf(m, ",group_id=%u", fc->group_id);
+       if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
+               seq_puts(m, ",default_permissions");
+       if (fc->flags & FUSE_ALLOW_OTHER)
+               seq_puts(m, ",allow_other");
+       if (fc->max_read != ~0)
+               seq_printf(m, ",max_read=%u", fc->max_read);
+       return 0;
+}
+
+static void free_conn(struct fuse_conn *fc)
+{
+       while (!list_empty(&fc->unused_list)) {
+               struct fuse_req *req;
+               req = list_entry(fc->unused_list.next, struct fuse_req, list);
+               list_del(&req->list);
+               fuse_request_free(req);
+       }
+       kfree(fc);
+}
+
+/* Must be called with the fuse lock held */
+void fuse_release_conn(struct fuse_conn *fc)
+{
+       fc->count--;
+       if (!fc->count)
+               free_conn(fc);
+}
+
+static struct fuse_conn *new_conn(void)
+{
+       struct fuse_conn *fc;
+
+       fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+       if (fc != NULL) {
+               int i;
+               memset(fc, 0, sizeof(*fc));
+               init_waitqueue_head(&fc->waitq);
+               INIT_LIST_HEAD(&fc->pending);
+               INIT_LIST_HEAD(&fc->processing);
+               INIT_LIST_HEAD(&fc->unused_list);
+               INIT_LIST_HEAD(&fc->background);
+               sema_init(&fc->outstanding_sem, 0);
+               init_rwsem(&fc->sbput_sem);
+               for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
+                       struct fuse_req *req = fuse_request_alloc();
+                       if (!req) {
+                               free_conn(fc);
+                               return NULL;
+                       }
+                       list_add(&req->list, &fc->unused_list);
+               }
+               fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
+               fc->bdi.unplug_io_fn = default_unplug_io_fn;
+               fc->reqctr = 0;
+       }
+       return fc;
+}
+
+static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
+{
+       struct fuse_conn *fc;
+
+       if (file->f_op != &fuse_dev_operations)
+               return ERR_PTR(-EINVAL);
+       fc = new_conn();
+       if (fc == NULL)
+               return ERR_PTR(-ENOMEM);
+       spin_lock(&fuse_lock);
+       if (file->private_data) {
+               free_conn(fc);
+               fc = ERR_PTR(-EINVAL);
+       } else {
+               file->private_data = fc;
+               *get_fuse_conn_super_p(sb) = fc;
+               fc->mounted = 1;
+               fc->connected = 1;
+               fc->count = 2;
+       }
+       spin_unlock(&fuse_lock);
+       return fc;
+}
+
+static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
+{
+       struct fuse_attr attr;
+       memset(&attr, 0, sizeof(attr));
+
+       attr.mode = mode;
+       attr.ino = FUSE_ROOT_ID;
+       return fuse_iget(sb, 1, 0, &attr);
+}
+
+static struct super_operations fuse_super_operations = {
+       .alloc_inode    = fuse_alloc_inode,
+       .destroy_inode  = fuse_destroy_inode,
+       .read_inode     = fuse_read_inode,
+       .clear_inode    = fuse_clear_inode,
+       .put_super      = fuse_put_super,
+       .statfs         = fuse_statfs,
+       .show_options   = fuse_show_options,
+};
+
+static int fuse_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct fuse_conn *fc;
+       struct inode *root;
+       struct fuse_mount_data d;
+       struct file *file;
+       int err;
+
+       if (!parse_fuse_opt((char *) data, &d))
+               return -EINVAL;
+
+       sb->s_blocksize = PAGE_CACHE_SIZE;
+       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+       sb->s_magic = FUSE_SUPER_MAGIC;
+       sb->s_op = &fuse_super_operations;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
+
+       file = fget(d.fd);
+       if (!file)
+               return -EINVAL;
+
+       fc = get_conn(file, sb);
+       fput(file);
+       if (IS_ERR(fc))
+               return PTR_ERR(fc);
+
+       fc->flags = d.flags;
+       fc->user_id = d.user_id;
+       fc->group_id = d.group_id;
+       fc->max_read = d.max_read;
+       if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
+               fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
+       fc->max_write = FUSE_MAX_IN / 2;
+
+       err = -ENOMEM;
+       root = get_root_inode(sb, d.rootmode);
+       if (root == NULL)
+               goto err;
+
+       sb->s_root = d_alloc_root(root);
+       if (!sb->s_root) {
+               iput(root);
+               goto err;
+       }
+       fuse_send_init(fc);
+       return 0;
+
+ err:
+       spin_lock(&fuse_lock);
+       fuse_release_conn(fc);
+       spin_unlock(&fuse_lock);
+       return err;
+}
+
+static struct super_block *fuse_get_sb(struct file_system_type *fs_type,
+                                      int flags, const char *dev_name,
+                                      void *raw_data)
+{
+       return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super);
+}
+
+static struct file_system_type fuse_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "fuse",
+       .get_sb         = fuse_get_sb,
+       .kill_sb        = kill_anon_super,
+};
+
+static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
+                                unsigned long flags)
+{
+       struct inode * inode = foo;
+
+       if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+           SLAB_CTOR_CONSTRUCTOR)
+               inode_init_once(inode);
+}
+
+static int __init fuse_fs_init(void)
+{
+       int err;
+
+       err = register_filesystem(&fuse_fs_type);
+       if (err)
+               printk("fuse: failed to register filesystem\n");
+       else {
+               fuse_inode_cachep = kmem_cache_create("fuse_inode",
+                                                     sizeof(struct fuse_inode),
+                                                     0, SLAB_HWCACHE_ALIGN,
+                                                     fuse_inode_init_once, NULL);
+               if (!fuse_inode_cachep) {
+                       unregister_filesystem(&fuse_fs_type);
+                       err = -ENOMEM;
+               }
+       }
+
+       return err;
+}
+
+static void fuse_fs_cleanup(void)
+{
+       unregister_filesystem(&fuse_fs_type);
+       kmem_cache_destroy(fuse_inode_cachep);
+}
+
+static int __init fuse_init(void)
+{
+       int res;
+
+       printk("fuse init (API version %i.%i)\n",
+              FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+
+       spin_lock_init(&fuse_lock);
+       res = fuse_fs_init();
+       if (res)
+               goto err;
+
+       res = fuse_dev_init();
+       if (res)
+               goto err_fs_cleanup;
+
+       return 0;
+
+ err_fs_cleanup:
+       fuse_fs_cleanup();
+ err:
+       return res;
+}
+
+static void __exit fuse_exit(void)
+{
+       printk(KERN_DEBUG "fuse exit\n");
+
+       fuse_fs_cleanup();
+       fuse_dev_cleanup();
+}
+
+module_init(fuse_init);
+module_exit(fuse_exit);
index b2d18200a003f0feb8cdd41fb7ad9cb0ed18dc15..59c5062cd63f3bcc8af85edbdabda742a0c88325 100644 (file)
@@ -284,6 +284,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
 
 static void hostfs_delete_inode(struct inode *inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
        if(HOSTFS_I(inode)->fd != -1) {
                close_file(&HOSTFS_I(inode)->fd);
                HOSTFS_I(inode)->fd = -1;
index 38b1741fa539f8a5ed060a72ee93bafcf2281e28..e3d17e9ea6c19b5b7790c477c2d8cd34b06c146e 100644 (file)
@@ -284,6 +284,7 @@ void hpfs_write_if_changed(struct inode *inode)
 
 void hpfs_delete_inode(struct inode *inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
        lock_kernel();
        hpfs_remove_fnode(inode->i_sb, inode->i_ino);
        unlock_kernel();
index 71df1b1e8f75a87910357025048b38ba7d382df6..f80a79ff156b5c4feafe54d17fee693fdec6b71c 100644 (file)
@@ -1034,19 +1034,21 @@ void generic_delete_inode(struct inode *inode)
        inodes_stat.nr_inodes--;
        spin_unlock(&inode_lock);
 
-       if (inode->i_data.nrpages)
-               truncate_inode_pages(&inode->i_data, 0);
-
        security_inode_delete(inode);
 
        if (op->delete_inode) {
                void (*delete)(struct inode *) = op->delete_inode;
                if (!is_bad_inode(inode))
                        DQUOT_INIT(inode);
-               /* s_op->delete_inode internally recalls clear_inode() */
+               /* Filesystems implementing their own
+                * s_op->delete_inode are required to call
+                * truncate_inode_pages and clear_inode()
+                * internally */
                delete(inode);
-       } else
+       } else {
+               truncate_inode_pages(&inode->i_data, 0);
                clear_inode(inode);
+       }
        spin_lock(&inode_lock);
        hlist_del_init(&inode->i_hash);
        spin_unlock(&inode_lock);
index c6ec66fd876682f4846f0638c2b3682a66b49f94..49bbc2be3d72937ba4719e656a140bf1c9ea7aba 100644 (file)
@@ -1340,8 +1340,7 @@ int journal_stop(handle_t *handle)
        if (handle->h_sync) {
                do {
                        old_handle_count = transaction->t_handle_count;
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(1);
+                       schedule_timeout_uninterruptible(1);
                } while (old_handle_count != transaction->t_handle_count);
        }
 
index 777b90057b893968a2718fb3163407811947c146..3dcc6d2162cb812f4d3392c8a40a8cc1aea326b7 100644 (file)
@@ -1744,6 +1744,7 @@ jffs_delete_inode(struct inode *inode)
        D3(printk("jffs_delete_inode(): inode->i_ino == %lu\n",
                  inode->i_ino));
 
+       truncate_inode_pages(&inode->i_data, 0);
        lock_kernel();
        inode->i_size = 0;
        inode->i_blocks = 0;
index 456d7e6e29c2683bd2fc4724b7980cb81171bfff..27f199e94cfc8edd369775b4e962eee517dc3a14 100644 (file)
@@ -1701,12 +1701,10 @@ jffs_find_file(struct jffs_control *c, __u32 ino)
 {
        struct jffs_file *f;
        int i = ino % c->hash_len;
-       struct list_head *tmp;
 
        D3(printk("jffs_find_file(): ino: %u\n", ino));
 
-       for (tmp = c->hash[i].next; tmp != &c->hash[i]; tmp = tmp->next) {
-               f = list_entry(tmp, struct jffs_file, hash);
+       list_for_each_entry(f, &c->hash[i], hash) {
                if (ino != f->ino)
                        continue;
                D3(printk("jffs_find_file(): Found file with ino "
@@ -2102,13 +2100,12 @@ jffs_foreach_file(struct jffs_control *c, int (*func)(struct jffs_file *))
        int result = 0;
 
        for (pos = 0; pos < c->hash_len; pos++) {
-               struct list_head *p, *next;
-               for (p = c->hash[pos].next; p != &c->hash[pos]; p = next) {
-                       /* We need a reference to the next file in the
-                          list because `func' might remove the current
-                          file `f'.  */
-                       next = p->next;
-                       r = func(list_entry(p, struct jffs_file, hash));
+               struct jffs_file *f, *next;
+
+               /* We must do _safe, because 'func' might remove the
+                  current file 'f' from the list.  */
+               list_for_each_entry_safe(f, next, &c->hash[pos], hash) {
+                       r = func(f);
                        if (r < 0)
                                return r;
                        result += r;
@@ -2613,9 +2610,8 @@ jffs_print_hash_table(struct jffs_control *c)
 
        printk("JFFS: Dumping the file system's hash table...\n");
        for (i = 0; i < c->hash_len; i++) {
-               struct list_head *p;
-               for (p = c->hash[i].next; p != &c->hash[i]; p = p->next) {
-                       struct jffs_file *f=list_entry(p,struct jffs_file,hash);
+               struct jffs_file *f;
+               list_for_each_entry(f, &c->hash[i], hash) {
                        printk("*** c->hash[%u]: \"%s\" "
                               "(ino: %u, pino: %u)\n",
                               i, (f->name ? f->name : ""),
index e892dab40c26ab4d0cd6f97804ae28dcdf5ccc77..461e4934ca7c280553190f9c7b34cc296a95a23a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/quotaops.h>
 #include <linux/posix_acl_xattr.h>
 #include "jfs_incore.h"
+#include "jfs_txnmgr.h"
 #include "jfs_xattr.h"
 #include "jfs_acl.h"
 
@@ -75,7 +76,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
+                      struct posix_acl *acl)
 {
        char *ea_name;
        struct jfs_inode_info *ji = JFS_IP(inode);
@@ -110,7 +112,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
                if (rc < 0)
                        goto out;
        }
-       rc = __jfs_setxattr(inode, ea_name, value, size, 0);
+       rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
 out:
        kfree(value);
 
@@ -143,7 +145,7 @@ int jfs_permission(struct inode *inode, int mask, struct nameidata *nd)
        return generic_permission(inode, mask, jfs_check_acl);
 }
 
-int jfs_init_acl(struct inode *inode, struct inode *dir)
+int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
 {
        struct posix_acl *acl = NULL;
        struct posix_acl *clone;
@@ -159,7 +161,7 @@ int jfs_init_acl(struct inode *inode, struct inode *dir)
 
        if (acl) {
                if (S_ISDIR(inode->i_mode)) {
-                       rc = jfs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+                       rc = jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, acl);
                        if (rc)
                                goto cleanup;
                }
@@ -173,7 +175,8 @@ int jfs_init_acl(struct inode *inode, struct inode *dir)
                if (rc >= 0) {
                        inode->i_mode = mode;
                        if (rc > 0)
-                               rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+                               rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS,
+                                                clone);
                }
                posix_acl_release(clone);
 cleanup:
@@ -202,8 +205,15 @@ static int jfs_acl_chmod(struct inode *inode)
                return -ENOMEM;
 
        rc = posix_acl_chmod_masq(clone, inode->i_mode);
-       if (!rc)
-               rc = jfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
+       if (!rc) {
+               tid_t tid = txBegin(inode->i_sb, 0);
+               down(&JFS_IP(inode)->commit_sem);
+               rc = jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, clone);
+               if (!rc)
+                       rc = txCommit(tid, 1, &inode, 0);
+               txEnd(tid);
+               up(&JFS_IP(inode)->commit_sem);
+       }
 
        posix_acl_release(clone);
        return rc;
index 767c7ecb429ed6f044e1954873c73c1d719eaab8..0ec62d5310db6a78128a948fd1370159caea0b09 100644 (file)
@@ -128,21 +128,23 @@ void jfs_delete_inode(struct inode *inode)
 {
        jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
 
-       if (is_bad_inode(inode) ||
-           (JFS_IP(inode)->fileset != cpu_to_le32(FILESYSTEM_I)))
-                       return;
+       if (!is_bad_inode(inode) &&
+           (JFS_IP(inode)->fileset == cpu_to_le32(FILESYSTEM_I))) {
 
-       if (test_cflag(COMMIT_Freewmap, inode))
-               jfs_free_zero_link(inode);
+               truncate_inode_pages(&inode->i_data, 0);
 
-       diFree(inode);
+               if (test_cflag(COMMIT_Freewmap, inode))
+                       jfs_free_zero_link(inode);
 
-       /*
-        * Free the inode from the quota allocation.
-        */
-       DQUOT_INIT(inode);
-       DQUOT_FREE_INODE(inode);
-       DQUOT_DROP(inode);
+               diFree(inode);
+
+               /*
+                * Free the inode from the quota allocation.
+                */
+               DQUOT_INIT(inode);
+               DQUOT_FREE_INODE(inode);
+               DQUOT_DROP(inode);
+       }
 
        clear_inode(inode);
 }
index a3acd3eec059c752acce63f35adb86fe15559aec..a76293767c73649048fb904698771b8d0da15845 100644 (file)
 #ifdef CONFIG_JFS_POSIX_ACL
 
 int jfs_permission(struct inode *, int, struct nameidata *);
-int jfs_init_acl(struct inode *, struct inode *);
+int jfs_init_acl(tid_t, struct inode *, struct inode *);
 int jfs_setattr(struct dentry *, struct iattr *);
 
-#endif         /* CONFIG_JFS_POSIX_ACL */
+#else
+
+static inline int jfs_init_acl(tid_t tid, struct inode *inode,
+                              struct inode *dir)
+{
+       return 0;
+}
+
+#endif
 #endif         /* _H_JFS_ACL */
index a1052f3f0bee0e2ed37d4d29e22583bf7cd7d3cb..25e9990bccd1be1926a21847d4135544a7dd4e42 100644 (file)
@@ -52,8 +52,8 @@ struct jfs_ea_list {
 #define        END_EALIST(ealist) \
        ((struct jfs_ea *) (((char *) (ealist)) + EALIST_SIZE(ealist)))
 
-extern int __jfs_setxattr(struct inode *, const char *, const void *, size_t,
-                         int);
+extern int __jfs_setxattr(tid_t, struct inode *, const char *, const void *,
+                         size_t, int);
 extern int jfs_setxattr(struct dentry *, const char *, const void *, size_t,
                        int);
 extern ssize_t __jfs_getxattr(struct inode *, const char *, void *, size_t);
@@ -61,4 +61,14 @@ extern ssize_t jfs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
 extern int jfs_removexattr(struct dentry *, const char *);
 
+#ifdef CONFIG_JFS_SECURITY
+extern int jfs_init_security(tid_t, struct inode *, struct inode *);
+#else
+static inline int jfs_init_security(tid_t tid, struct inode *inode,
+                                   struct inode *dir)
+{
+       return 0;
+}
+#endif
+
 #endif /* H_JFS_XATTR */
index 49ccde3937f97ec7d8bf4e28cb2955dea69b08d4..1abe7343f920494451b3bb5e5165f31af471eac6 100644 (file)
@@ -38,6 +38,24 @@ struct dentry_operations jfs_ci_dentry_operations;
 
 static s64 commitZeroLink(tid_t, struct inode *);
 
+/*
+ * NAME:       free_ea_wmap(inode)
+ *
+ * FUNCTION:   free uncommitted extended attributes from working map 
+ *
+ */
+static inline void free_ea_wmap(struct inode *inode)
+{
+       dxd_t *ea = &JFS_IP(inode)->ea;
+
+       if (ea->flag & DXD_EXTENT) {
+               /* free EA pages from cache */
+               invalidate_dxd_metapages(inode, *ea);
+               dbFree(inode, addressDXD(ea), lengthDXD(ea));
+       }
+       ea->flag = 0;
+}
+
 /*
  * NAME:       jfs_create(dip, dentry, mode)
  *
@@ -89,8 +107,19 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
        down(&JFS_IP(dip)->commit_sem);
        down(&JFS_IP(ip)->commit_sem);
 
+       rc = jfs_init_acl(tid, ip, dip);
+       if (rc)
+               goto out3;
+
+       rc = jfs_init_security(tid, ip, dip);
+       if (rc) {
+               txAbort(tid, 0);
+               goto out3;
+       }
+
        if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
                jfs_err("jfs_create: dtSearch returned %d", rc);
+               txAbort(tid, 0);
                goto out3;
        }
 
@@ -139,6 +168,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
        up(&JFS_IP(dip)->commit_sem);
        up(&JFS_IP(ip)->commit_sem);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -147,11 +177,6 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
       out2:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dip);
-#endif
-
       out1:
 
        jfs_info("jfs_create: rc:%d", rc);
@@ -216,8 +241,19 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
        down(&JFS_IP(dip)->commit_sem);
        down(&JFS_IP(ip)->commit_sem);
 
+       rc = jfs_init_acl(tid, ip, dip);
+       if (rc)
+               goto out3;
+
+       rc = jfs_init_security(tid, ip, dip);
+       if (rc) {
+               txAbort(tid, 0);
+               goto out3;
+       }
+
        if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
                jfs_err("jfs_mkdir: dtSearch returned %d", rc);
+               txAbort(tid, 0);
                goto out3;
        }
 
@@ -267,6 +303,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
        up(&JFS_IP(dip)->commit_sem);
        up(&JFS_IP(ip)->commit_sem);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -275,10 +312,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
       out2:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dip);
-#endif
 
       out1:
 
@@ -885,6 +918,10 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        down(&JFS_IP(dip)->commit_sem);
        down(&JFS_IP(ip)->commit_sem);
 
+       rc = jfs_init_security(tid, ip, dip);
+       if (rc)
+               goto out3;
+
        tblk = tid_to_tblock(tid);
        tblk->xflag |= COMMIT_CREATE;
        tblk->ino = ip->i_ino;
@@ -1000,6 +1037,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
        up(&JFS_IP(dip)->commit_sem);
        up(&JFS_IP(ip)->commit_sem);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -1008,11 +1046,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
       out2:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dip);
-#endif
-
       out1:
        jfs_info("jfs_symlink: rc:%d", rc);
        return rc;
@@ -1328,8 +1361,20 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        down(&JFS_IP(dir)->commit_sem);
        down(&JFS_IP(ip)->commit_sem);
 
-       if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
+       rc = jfs_init_acl(tid, ip, dir);
+       if (rc)
+               goto out3;
+
+       rc = jfs_init_security(tid, ip, dir);
+       if (rc) {
+               txAbort(tid, 0);
                goto out3;
+       }
+
+       if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {
+               txAbort(tid, 0);
+               goto out3;
+       }
 
        tblk = tid_to_tblock(tid);
        tblk->xflag |= COMMIT_CREATE;
@@ -1337,8 +1382,10 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
 
        ino = ip->i_ino;
-       if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
+       if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {
+               txAbort(tid, 0);
                goto out3;
+       }
 
        ip->i_op = &jfs_file_inode_operations;
        jfs_ip->dev = new_encode_dev(rdev);
@@ -1360,6 +1407,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        up(&JFS_IP(ip)->commit_sem);
        up(&JFS_IP(dir)->commit_sem);
        if (rc) {
+               free_ea_wmap(ip);
                ip->i_nlink = 0;
                iput(ip);
        } else
@@ -1368,11 +1416,6 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
       out1:
        free_UCSname(&dname);
 
-#ifdef CONFIG_JFS_POSIX_ACL
-       if (rc == 0)
-               jfs_init_acl(ip, dir);
-#endif
-
       out:
        jfs_info("jfs_mknod: returning %d", rc);
        return rc;
index 554ec739e49b9d41f6f35cecefcb03164b177d44..23aa5066b5a438014d84a2d0491c79e49b25e4dd 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/xattr.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/quotaops.h>
+#include <linux/security.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
@@ -633,12 +634,12 @@ static void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
        }
 }
 
-static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
+static int ea_put(tid_t tid, struct inode *inode, struct ea_buffer *ea_buf,
+                 int new_size)
 {
        struct jfs_inode_info *ji = JFS_IP(inode);
        unsigned long old_blocks, new_blocks;
        int rc = 0;
-       tid_t tid;
 
        if (new_size == 0) {
                ea_release(inode, ea_buf);
@@ -664,9 +665,6 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
        if (rc)
                return rc;
 
-       tid = txBegin(inode->i_sb, 0);
-       down(&ji->commit_sem);
-
        old_blocks = new_blocks = 0;
 
        if (ji->ea.flag & DXD_EXTENT) {
@@ -695,11 +693,8 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
                DQUOT_FREE_BLOCK(inode, old_blocks);
 
        inode->i_ctime = CURRENT_TIME;
-       rc = txCommit(tid, 1, &inode, 0);
-       txEnd(tid);
-       up(&ji->commit_sem);
 
-       return rc;
+       return 0;
 }
 
 /*
@@ -810,8 +805,8 @@ static int can_set_xattr(struct inode *inode, const char *name,
        return permission(inode, MAY_WRITE, NULL);
 }
 
-int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
-                  size_t value_len, int flags)
+int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
+                  const void *value, size_t value_len, int flags)
 {
        struct jfs_ea_list *ealist;
        struct jfs_ea *ea, *old_ea = NULL, *next_ea = NULL;
@@ -825,9 +820,6 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
        int rc;
        int length;
 
-       if ((rc = can_set_xattr(inode, name, value, value_len)))
-               return rc;
-
        if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
                os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
                                  GFP_KERNEL);
@@ -939,7 +931,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
 
        ealist->size = cpu_to_le32(new_size);
 
-       rc = ea_put(inode, &ea_buf, new_size);
+       rc = ea_put(tid, inode, &ea_buf, new_size);
 
        goto out;
       release:
@@ -955,12 +947,29 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
 int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                 size_t value_len, int flags)
 {
+       struct inode *inode = dentry->d_inode;
+       struct jfs_inode_info *ji = JFS_IP(inode);
+       int rc;
+       tid_t tid;
+
+       if ((rc = can_set_xattr(inode, name, value, value_len)))
+               return rc;
+
        if (value == NULL) {    /* empty EA, do not remove */
                value = "";
                value_len = 0;
        }
 
-       return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
+       tid = txBegin(inode->i_sb, 0);
+       down(&ji->commit_sem);
+       rc = __jfs_setxattr(tid, dentry->d_inode, name, value, value_len,
+                           flags);
+       if (!rc)
+               rc = txCommit(tid, 1, &inode, 0);
+       txEnd(tid);
+       up(&ji->commit_sem);
+
+       return rc;
 }
 
 static int can_get_xattr(struct inode *inode, const char *name)
@@ -1122,5 +1131,56 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
 
 int jfs_removexattr(struct dentry *dentry, const char *name)
 {
-       return __jfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+       struct inode *inode = dentry->d_inode;
+       struct jfs_inode_info *ji = JFS_IP(inode);
+       int rc;
+       tid_t tid;
+
+       if ((rc = can_set_xattr(inode, name, NULL, 0)))
+               return rc;
+
+       tid = txBegin(inode->i_sb, 0);
+       down(&ji->commit_sem);
+       rc = __jfs_setxattr(tid, dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+       if (!rc)
+               rc = txCommit(tid, 1, &inode, 0);
+       txEnd(tid);
+       up(&ji->commit_sem);
+
+       return rc;
+}
+
+#ifdef CONFIG_JFS_SECURITY
+int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir)
+{
+       int rc;
+       size_t len;
+       void *value;
+       char *suffix;
+       char *name;
+
+       rc = security_inode_init_security(inode, dir, &suffix, &value, &len);
+       if (rc) {
+               if (rc == -EOPNOTSUPP)
+                       return 0;
+               return rc;
+       }
+       name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix),
+                      GFP_NOFS);
+       if (!name) {
+               rc = -ENOMEM;
+               goto kmalloc_failed;
+       }
+       strcpy(name, XATTR_SECURITY_PREFIX);
+       strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
+
+       rc = __jfs_setxattr(tid, inode, name, value, len, 0);
+
+       kfree(name);
+kmalloc_failed:
+       kfree(suffix);
+       kfree(value);
+
+       return rc;
 }
+#endif
index 14b3ce87fa29cd96162678fb754936e22c99caec..87332f30141b621b7478f3faacfac6e4c226d991 100644 (file)
@@ -299,8 +299,7 @@ nlmclnt_alloc_call(void)
                        return call;
                }
                printk("nlmclnt_alloc_call: failed, waiting for memory\n");
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(5*HZ);
+               schedule_timeout_interruptible(5*HZ);
        }
        return NULL;
 }
index 11956b6179ff81a9924ab099896a07ba3892bc0b..c2c09b4798d606b4bc9e5d56a518beef021543f3 100644 (file)
@@ -2198,21 +2198,23 @@ void steal_locks(fl_owner_t from)
 {
        struct files_struct *files = current->files;
        int i, j;
+       struct fdtable *fdt;
 
        if (from == files)
                return;
 
        lock_kernel();
        j = 0;
+       fdt = files_fdtable(files);
        for (;;) {
                unsigned long set;
                i = j * __NFDBITS;
-               if (i >= files->max_fdset || i >= files->max_fds)
+               if (i >= fdt->max_fdset || i >= fdt->max_fds)
                        break;
-               set = files->open_fds->fds_bits[j++];
+               set = fdt->open_fds->fds_bits[j++];
                while (set) {
                        if (set & 1) {
-                               struct file *file = files->fd[i];
+                               struct file *file = fdt->fd[i];
                                if (file)
                                        __steal_locks(file, from);
                        }
index 3f18c21198d7e2a848573e539316844c3fe2e142..790cc0d0e970a643b7387ea964eb1e8d7fde0fcc 100644 (file)
@@ -24,6 +24,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data);
 
 static void minix_delete_inode(struct inode *inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
        inode->i_size = 0;
        minix_truncate(inode);
        minix_free_inode(inode);
index 145e852c4bd02d717c3dd9e3b63caa6804870f25..21d85f1ac8395f82376e2dd5073494d568080e78 100644 (file)
@@ -1316,10 +1316,8 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
                return error;
        DQUOT_INIT(dir);
        error = dir->i_op->create(dir, dentry, mode, nd);
-       if (!error) {
+       if (!error)
                fsnotify_create(dir, dentry->d_name.name);
-               security_inode_post_create(dir, dentry, mode);
-       }
        return error;
 }
 
@@ -1635,10 +1633,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 
        DQUOT_INIT(dir);
        error = dir->i_op->mknod(dir, dentry, mode, dev);
-       if (!error) {
+       if (!error)
                fsnotify_create(dir, dentry->d_name.name);
-               security_inode_post_mknod(dir, dentry, mode, dev);
-       }
        return error;
 }
 
@@ -1708,10 +1704,8 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        DQUOT_INIT(dir);
        error = dir->i_op->mkdir(dir, dentry, mode);
-       if (!error) {
+       if (!error)
                fsnotify_mkdir(dir, dentry->d_name.name);
-               security_inode_post_mkdir(dir,dentry, mode);
-       }
        return error;
 }
 
@@ -1947,10 +1941,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
 
        DQUOT_INIT(dir);
        error = dir->i_op->symlink(dir, dentry, oldname);
-       if (!error) {
+       if (!error)
                fsnotify_create(dir, dentry->d_name.name);
-               security_inode_post_symlink(dir, dentry, oldname);
-       }
        return error;
 }
 
@@ -2020,10 +2012,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
        DQUOT_INIT(dir);
        error = dir->i_op->link(old_dentry, dir, new_dentry);
        up(&old_dentry->d_inode->i_sem);
-       if (!error) {
+       if (!error)
                fsnotify_create(dir, new_dentry->d_name.name);
-               security_inode_post_link(old_dentry, dir, new_dentry);
-       }
        return error;
 }
 
@@ -2142,11 +2132,8 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
                        d_rehash(new_dentry);
                dput(new_dentry);
        }
-       if (!error) {
+       if (!error)
                d_move(old_dentry,new_dentry);
-               security_inode_post_rename(old_dir, old_dentry,
-                                          new_dir, new_dentry);
-       }
        return error;
 }
 
@@ -2172,7 +2159,6 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
                /* The following d_move() should become unconditional */
                if (!(old_dir->i_sb->s_type->fs_flags & FS_ODD_RENAME))
                        d_move(old_dentry, new_dentry);
-               security_inode_post_rename(old_dir, old_dentry, new_dir, new_dentry);
        }
        if (target)
                up(&target->i_sem);
index 34156260c9b6586939e932e3856cc0211e98cd97..2fa9fdf7d6f573f1f6b004ab82d9a0945d9a6f9c 100644 (file)
@@ -537,7 +537,6 @@ lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
 static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
 {
        struct vfsmount *res, *p, *q, *r, *s;
-       struct list_head *h;
        struct nameidata nd;
 
        res = q = clone_mnt(mnt, dentry);
@@ -546,8 +545,7 @@ static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry)
        q->mnt_mountpoint = mnt->mnt_mountpoint;
 
        p = mnt;
-       for (h = mnt->mnt_mounts.next; h != &mnt->mnt_mounts; h = h->next) {
-               r = list_entry(h, struct vfsmount, mnt_child);
+       list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
                if (!lives_below_in_same_fs(r->mnt_mountpoint, dentry))
                        continue;
 
index 44795d2f4b30856790ce214d2c10386c1122cf6b..8c8839203cd5a0bae7e0e4cb0fec352748b02391 100644 (file)
@@ -286,6 +286,8 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 static void
 ncp_delete_inode(struct inode *inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
+
        if (S_ISDIR(inode->i_mode)) {
                DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
        }
index 541b418327c8b18b8f30d294beca9c10d3ca732e..6922469d6fc573415a09a642ae01cf96b72a8879 100644 (file)
@@ -146,6 +146,8 @@ nfs_delete_inode(struct inode * inode)
 {
        dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
 
+       truncate_inode_pages(&inode->i_data, 0);
+
        nfs_wb_all(inode);
        /*
         * The following should never happen...
index 2681485cf2d00f9f9fdd647a8bf1cd9861299104..edc95514046d50415b127988fc36ae577b8b3d97 100644 (file)
@@ -34,8 +34,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
                res = rpc_call_sync(clnt, msg, flags);
                if (res != -EJUKEBOX)
                        break;
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(NFS_JUKEBOX_RETRY_TIME);
+               schedule_timeout_interruptible(NFS_JUKEBOX_RETRY_TIME);
                res = -ERESTARTSYS;
        } while (!signalled());
        rpc_clnt_sigunmask(clnt, &oldset);
index 0c5a308e49638171291d22aa3630fc431ac74528..9701ca8c942855a719ccd98559fd878c60ee636c 100644 (file)
@@ -2418,14 +2418,11 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
                *timeout = NFS4_POLL_RETRY_MAX;
        rpc_clnt_sigmask(clnt, &oldset);
        if (clnt->cl_intr) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(*timeout);
+               schedule_timeout_interruptible(*timeout);
                if (signalled())
                        res = -ERESTARTSYS;
-       } else {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(*timeout);
-       }
+       } else
+               schedule_timeout_uninterruptible(*timeout);
        rpc_clnt_sigunmask(clnt, &oldset);
        *timeout <<= 1;
        return res;
@@ -2578,8 +2575,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4
 static unsigned long
 nfs4_set_lock_task_retry(unsigned long timeout)
 {
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(timeout);
+       schedule_timeout_interruptible(timeout);
        timeout <<= 1;
        if (timeout > NFS4_LOCK_MAXTIMEOUT)
                return NFS4_LOCK_MAXTIMEOUT;
index 545236414d592b7f3abdf810799f64ae758ca2d2..b6cc8cf24626b0a1f15ec8deffddc704da797c0e 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/swap.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
+#include <linux/bit_spinlock.h>
 
 #include "aops.h"
 #include "attrib.h"
index 4ee2dcc31c285dc57c6922b21e1bad80e740b6c3..2fac58c51910cf250607a8f7161edc608d8c18cc 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -24,6 +24,7 @@
 #include <linux/personality.h>
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
+#include <linux/rcupdate.h>
 
 #include <asm/unistd.h>
 
@@ -842,14 +843,16 @@ int get_unused_fd(void)
 {
        struct files_struct * files = current->files;
        int fd, error;
+       struct fdtable *fdt;
 
        error = -EMFILE;
        spin_lock(&files->file_lock);
 
 repeat:
-       fd = find_next_zero_bit(files->open_fds->fds_bits, 
-                               files->max_fdset, 
-                               files->next_fd);
+       fdt = files_fdtable(files);
+       fd = find_next_zero_bit(fdt->open_fds->fds_bits,
+                               fdt->max_fdset,
+                               fdt->next_fd);
 
        /*
         * N.B. For clone tasks sharing a files structure, this test
@@ -872,14 +875,14 @@ repeat:
                goto repeat;
        }
 
-       FD_SET(fd, files->open_fds);
-       FD_CLR(fd, files->close_on_exec);
-       files->next_fd = fd + 1;
+       FD_SET(fd, fdt->open_fds);
+       FD_CLR(fd, fdt->close_on_exec);
+       fdt->next_fd = fd + 1;
 #if 1
        /* Sanity check */
-       if (files->fd[fd] != NULL) {
+       if (fdt->fd[fd] != NULL) {
                printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
-               files->fd[fd] = NULL;
+               fdt->fd[fd] = NULL;
        }
 #endif
        error = fd;
@@ -893,9 +896,10 @@ EXPORT_SYMBOL(get_unused_fd);
 
 static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
 {
-       __FD_CLR(fd, files->open_fds);
-       if (fd < files->next_fd)
-               files->next_fd = fd;
+       struct fdtable *fdt = files_fdtable(files);
+       __FD_CLR(fd, fdt->open_fds);
+       if (fd < fdt->next_fd)
+               fdt->next_fd = fd;
 }
 
 void fastcall put_unused_fd(unsigned int fd)
@@ -924,10 +928,11 @@ EXPORT_SYMBOL(put_unused_fd);
 void fastcall fd_install(unsigned int fd, struct file * file)
 {
        struct files_struct *files = current->files;
+       struct fdtable *fdt;
        spin_lock(&files->file_lock);
-       if (unlikely(files->fd[fd] != NULL))
-               BUG();
-       files->fd[fd] = file;
+       fdt = files_fdtable(files);
+       BUG_ON(fdt->fd[fd] != NULL);
+       rcu_assign_pointer(fdt->fd[fd], file);
        spin_unlock(&files->file_lock);
 }
 
@@ -1010,15 +1015,17 @@ asmlinkage long sys_close(unsigned int fd)
 {
        struct file * filp;
        struct files_struct *files = current->files;
+       struct fdtable *fdt;
 
        spin_lock(&files->file_lock);
-       if (fd >= files->max_fds)
+       fdt = files_fdtable(files);
+       if (fd >= fdt->max_fds)
                goto out_unlock;
-       filp = files->fd[fd];
+       filp = fdt->fd[fd];
        if (!filp)
                goto out_unlock;
-       files->fd[fd] = NULL;
-       FD_CLR(fd, files->close_on_exec);
+       rcu_assign_pointer(fdt->fd[fd], NULL);
+       FD_CLR(fd, fdt->close_on_exec);
        __put_unused_fd(files, fd);
        spin_unlock(&files->file_lock);
        return filp_close(filp, files);
index 2c7a23dde2d83f1ae18190e5723c0eb8d8ae0548..66aa0b938d6aca876bf2d246462c5fa2e3586e8b 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -39,7 +39,11 @@ void pipe_wait(struct inode * inode)
 {
        DEFINE_WAIT(wait);
 
-       prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE);
+       /*
+        * Pipes are system-local resources, so sleeping on them
+        * is considered a noninteractive wait:
+        */
+       prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE);
        up(PIPE_SEM(*inode));
        schedule();
        finish_wait(PIPE_WAIT(*inode), &wait);
index 37668fe998ad0f28aa5253138ba42351b4bf0d17..d88d518d30f605d216ba292e20be281cacf0eab4 100644 (file)
@@ -159,6 +159,7 @@ static inline char * task_state(struct task_struct *p, char *buffer)
 {
        struct group_info *group_info;
        int g;
+       struct fdtable *fdt = NULL;
 
        read_lock(&tasklist_lock);
        buffer += sprintf(buffer,
@@ -179,10 +180,12 @@ static inline char * task_state(struct task_struct *p, char *buffer)
                p->gid, p->egid, p->sgid, p->fsgid);
        read_unlock(&tasklist_lock);
        task_lock(p);
+       if (p->files)
+               fdt = files_fdtable(p->files);
        buffer += sprintf(buffer,
                "FDSize:\t%d\n"
                "Groups:\t",
-               p->files ? p->files->max_fds : 0);
+               fdt ? fdt->max_fds : 0);
 
        group_info = p->group_info;
        get_group_info(group_info);
index 84751f3f52d530e86518247e3cace7d20646ed80..23db452ab428c9896a96aad29217100e67aeb78a 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/namespace.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
+#include <linux/rcupdate.h>
 #include <linux/kallsyms.h>
 #include <linux/mount.h>
 #include <linux/security.h>
@@ -283,16 +284,16 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
 
        files = get_files_struct(task);
        if (files) {
-               spin_lock(&files->file_lock);
+               rcu_read_lock();
                file = fcheck_files(files, fd);
                if (file) {
                        *mnt = mntget(file->f_vfsmnt);
                        *dentry = dget(file->f_dentry);
-                       spin_unlock(&files->file_lock);
+                       rcu_read_unlock();
                        put_files_struct(files);
                        return 0;
                }
-               spin_unlock(&files->file_lock);
+               rcu_read_unlock();
                put_files_struct(files);
        }
        return -ENOENT;
@@ -1039,6 +1040,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
        int retval;
        char buf[NUMBUF];
        struct files_struct * files;
+       struct fdtable *fdt;
 
        retval = -ENOENT;
        if (!pid_alive(p))
@@ -1061,15 +1063,16 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
                        files = get_files_struct(p);
                        if (!files)
                                goto out;
-                       spin_lock(&files->file_lock);
+                       rcu_read_lock();
+                       fdt = files_fdtable(files);
                        for (fd = filp->f_pos-2;
-                            fd < files->max_fds;
+                            fd < fdt->max_fds;
                             fd++, filp->f_pos++) {
                                unsigned int i,j;
 
                                if (!fcheck_files(files, fd))
                                        continue;
-                               spin_unlock(&files->file_lock);
+                               rcu_read_unlock();
 
                                j = NUMBUF;
                                i = fd;
@@ -1081,12 +1084,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 
                                ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
                                if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
-                                       spin_lock(&files->file_lock);
+                                       rcu_read_lock();
                                        break;
                                }
-                               spin_lock(&files->file_lock);
+                               rcu_read_lock();
                        }
-                       spin_unlock(&files->file_lock);
+                       rcu_read_unlock();
                        put_files_struct(files);
        }
 out:
@@ -1261,9 +1264,9 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
 
        files = get_files_struct(task);
        if (files) {
-               spin_lock(&files->file_lock);
+               rcu_read_lock();
                if (fcheck_files(files, fd)) {
-                       spin_unlock(&files->file_lock);
+                       rcu_read_unlock();
                        put_files_struct(files);
                        if (task_dumpable(task)) {
                                inode->i_uid = task->euid;
@@ -1275,7 +1278,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
                        security_task_to_inode(task, inode);
                        return 1;
                }
-               spin_unlock(&files->file_lock);
+               rcu_read_unlock();
                put_files_struct(files);
        }
        d_drop(dentry);
@@ -1367,7 +1370,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
        if (!files)
                goto out_unlock;
        inode->i_mode = S_IFLNK;
-       spin_lock(&files->file_lock);
+       rcu_read_lock();
        file = fcheck_files(files, fd);
        if (!file)
                goto out_unlock2;
@@ -1375,7 +1378,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
                inode->i_mode |= S_IRUSR | S_IXUSR;
        if (file->f_mode & 2)
                inode->i_mode |= S_IWUSR | S_IXUSR;
-       spin_unlock(&files->file_lock);
+       rcu_read_unlock();
        put_files_struct(files);
        inode->i_op = &proc_pid_link_inode_operations;
        inode->i_size = 64;
@@ -1385,7 +1388,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
        return NULL;
 
 out_unlock2:
-       spin_unlock(&files->file_lock);
+       rcu_read_unlock();
        put_files_struct(files);
 out_unlock:
        iput(inode);
index 133c28685105613c5f92c50b52e26c6b97d7bde6..effa6c0c467ac083d9b62fb34b56a2946596ef27 100644 (file)
@@ -60,6 +60,8 @@ static void proc_delete_inode(struct inode *inode)
        struct proc_dir_entry *de;
        struct task_struct *tsk;
 
+       truncate_inode_pages(&inode->i_data, 0);
+
        /* Let go of any associated process */
        tsk = PROC_I(inode)->task;
        if (tsk)
index b79162a35478ce46fae25af21067844b0fabfd4b..80f32911c0cb4bea686459920215191377287e01 100644 (file)
@@ -63,6 +63,7 @@ int qnx4_sync_inode(struct inode *inode)
 static void qnx4_delete_inode(struct inode *inode)
 {
        QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
+       truncate_inode_pages(&inode->i_data, 0);
        inode->i_size = 0;
        qnx4_truncate(inode);
        lock_kernel();
index ff291c973a567f4d9226c3840c98ea002c4ed823..1a8a1bf2154d10475a0bacc89b085070587d48d6 100644 (file)
@@ -33,6 +33,8 @@ void reiserfs_delete_inode(struct inode *inode)
            2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
        struct reiserfs_transaction_handle th;
 
+       truncate_inode_pages(&inode->i_data, 0);
+
        reiserfs_write_lock(inode->i_sb);
 
        /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
index a8e29e9bbbd08e336fc13a3fd9b1e81d7ec4eda0..4b15761434bc7fac7c494703267995a9b49a6ff2 100644 (file)
@@ -2868,8 +2868,7 @@ static void let_transaction_grow(struct super_block *sb, unsigned long trans_id)
        struct reiserfs_journal *journal = SB_JOURNAL(sb);
        unsigned long bcount = journal->j_bcount;
        while (1) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_uninterruptible(1);
                journal->j_current_jl->j_state |= LIST_COMMIT_PENDING;
                while ((atomic_read(&journal->j_wcount) > 0 ||
                        atomic_read(&journal->j_jlock)) &&
index 6951c35755beba2502c5e405356a9ff038100189..44b02fc02ebefa3121b2e2956ac4c35fdd1f48ed 100644 (file)
@@ -1934,8 +1934,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                        if (SB_AP_BITMAP(s))
                                brelse(SB_AP_BITMAP(s)[j].bh);
                }
-               if (SB_AP_BITMAP(s))
-                       vfree(SB_AP_BITMAP(s));
+               vfree(SB_AP_BITMAP(s));
        }
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
index b80e7eb0ac0dac26325c8ac0d2b7d992c1d7da20..f10a10317d5494e0eb4995d9c016113a093f34ee 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/personality.h> /* for STICKY_TIMEOUTS */
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 
@@ -132,11 +133,13 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds)
        unsigned long *open_fds;
        unsigned long set;
        int max;
+       struct fdtable *fdt;
 
        /* handle last in-complete long-word first */
        set = ~(~0UL << (n & (__NFDBITS-1)));
        n /= __NFDBITS;
-       open_fds = current->files->open_fds->fds_bits+n;
+       fdt = files_fdtable(current->files);
+       open_fds = fdt->open_fds->fds_bits+n;
        max = 0;
        if (set) {
                set &= BITS(fds, n);
@@ -183,9 +186,9 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
        int retval, i;
        long __timeout = *timeout;
 
-       spin_lock(&current->files->file_lock);
+       rcu_read_lock();
        retval = max_select_fd(n, fds);
-       spin_unlock(&current->files->file_lock);
+       rcu_read_unlock();
 
        if (retval < 0)
                return retval;
@@ -299,6 +302,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
        char *bits;
        long timeout;
        int ret, size, max_fdset;
+       struct fdtable *fdt;
 
        timeout = MAX_SCHEDULE_TIMEOUT;
        if (tvp) {
@@ -326,7 +330,10 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
                goto out_nofds;
 
        /* max_fdset can increase, so grab it once to avoid race */
-       max_fdset = current->files->max_fdset;
+       rcu_read_lock();
+       fdt = files_fdtable(current->files);
+       max_fdset = fdt->max_fdset;
+       rcu_read_unlock();
        if (n > max_fdset)
                n = max_fdset;
 
@@ -464,9 +471,15 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
        unsigned int i;
        struct poll_list *head;
        struct poll_list *walk;
+       struct fdtable *fdt;
+       int max_fdset;
 
        /* Do a sanity check on nfds ... */
-       if (nfds > current->files->max_fdset && nfds > OPEN_MAX)
+       rcu_read_lock();
+       fdt = files_fdtable(current->files);
+       max_fdset = fdt->max_fdset;
+       rcu_read_unlock();
+       if (nfds > max_fdset && nfds > OPEN_MAX)
                return -EINVAL;
 
        if (timeout) {
index 4765aaac9fd2ca1febfae1a13445c19992fb3769..10b994428fef29e6c43747ed2ae5345d264f8bbb 100644 (file)
@@ -331,6 +331,7 @@ static void
 smb_delete_inode(struct inode *ino)
 {
        DEBUG1("ino=%ld\n", ino->i_ino);
+       truncate_inode_pages(&ino->i_data, 0);
        lock_kernel();
        if (smb_close(ino))
                PARANOIA("could not close inode %ld\n", ino->i_ino);
index 220babe91efd1e8ebdb612a8dbdb56dd52ceb15f..38ab558835c4ba1348dad8738bcc1df7997df598 100644 (file)
@@ -2397,8 +2397,7 @@ smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
                if (req->rq_rcls == ERRSRV && req->rq_err == ERRerror) {
                        /* a damn Win95 bug - sometimes it clags if you 
                           ask it too fast */
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout(HZ/5);
+                       schedule_timeout_interruptible(msecs_to_jiffies(200));
                        continue;
                 }
 
index 0530077d9dd800b8e1fd897bae95edb524e1336e..fa33eceb00113d05bb826a15300c9971e45cb348 100644 (file)
@@ -292,6 +292,7 @@ int sysv_sync_inode(struct inode * inode)
 
 static void sysv_delete_inode(struct inode *inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
        inode->i_size = 0;
        sysv_truncate(inode);
        lock_kernel();
index 3d68de39fad6297dbfaed66e9f02b57e21ca604f..b83890beaaacbec45e199c9cf8fc78599423ff07 100644 (file)
@@ -87,6 +87,8 @@ static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
  */
 void udf_delete_inode(struct inode * inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
+
        if (is_bad_inode(inode))
                goto no_delete;
 
index 718627ca8b5c6b866fc826efb061f0fffe798856..55f4aa16e3fc930259964fabbb0dce8c905fccbb 100644 (file)
@@ -804,6 +804,7 @@ int ufs_sync_inode (struct inode *inode)
 
 void ufs_delete_inode (struct inode * inode)
 {
+       truncate_inode_pages(&inode->i_data, 0);
        /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
        lock_kernel();
        mark_inode_dirty(inode);
index 6c6fd0faa8e1fb26fedfb8d1174e228921b4c08e..b0d2873ab2747032118ded993a6e52d389cd80ea 100644 (file)
@@ -39,8 +39,7 @@ typedef struct timespec timespec_t;
 
 static inline void delay(long ticks)
 {
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(ticks);
+       schedule_timeout_uninterruptible(ticks);
 }
 
 static inline void nanotime(struct timespec *tvp)
index 655bf4a78afeb72a57eaf4668b2034b3c85c6aa7..e82cf72ac599a55aad2539c6fe0158f2788b15d0 100644 (file)
@@ -1780,10 +1780,10 @@ xfsbufd(
                        xfsbufd_force_sleep = 0;
                }
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100);
+               schedule_timeout_interruptible
+                       (xfs_buf_timer_centisecs * msecs_to_jiffies(10));
 
-               age = (xfs_buf_age_centisecs * HZ) / 100;
+               age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
                spin_lock(&pbd_delwrite_lock);
                list_for_each_entry_safe(pb, n, &pbd_delwrite_queue, pb_list) {
                        PB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
index 0da87bfc999999e74a32985ffbde515c429cd111..2302454d8d479d72eeeda5bb472633511ff1d4f7 100644 (file)
@@ -467,7 +467,7 @@ xfs_flush_inode(
 
        igrab(inode);
        xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
-       delay(HZ/2);
+       delay(msecs_to_jiffies(500));
 }
 
 /*
@@ -492,7 +492,7 @@ xfs_flush_device(
 
        igrab(inode);
        xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
-       delay(HZ/2);
+       delay(msecs_to_jiffies(500));
        xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 }
 
@@ -520,10 +520,9 @@ xfssyncd(
        struct vfs_sync_work    *work, *n;
        LIST_HEAD               (tmp);
 
-       timeleft = (xfs_syncd_centisecs * HZ) / 100;
+       timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
        for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               timeleft = schedule_timeout(timeleft);
+               timeleft = schedule_timeout_interruptible(timeleft);
                /* swsusp */
                try_to_freeze();
                if (kthread_should_stop())
@@ -537,7 +536,8 @@ xfssyncd(
                 */
                if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
                        if (!timeleft)
-                               timeleft = (xfs_syncd_centisecs * HZ) / 100;
+                               timeleft = xfs_syncd_centisecs *
+                                                       msecs_to_jiffies(10);
                        INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
                        list_add_tail(&vfsp->vfs_sync_work.w_list,
                                        &vfsp->vfs_sync_list);
index 3dae14c8c55a14eef89683f713e4b5af5f618c2f..fa8394f9437d4bafd80c8ac88f291cfb38e76468 100644 (file)
@@ -170,7 +170,7 @@ ktrace_enter(
        void            *val14,
        void            *val15)
 {
-       static lock_t   wrap_lock = SPIN_LOCK_UNLOCKED;
+       static DEFINE_SPINLOCK(wrap_lock);
        unsigned long   flags;
        int             index;
        ktrace_entry_t  *ktep;
index 80780dba9986fb47b78c204e5c23ab6b77a2fddf..8197c69eff44cdbebed4823db0bfdf0c1a2428fd 100644 (file)
@@ -6,7 +6,6 @@
 #include <linux/kernel.h>
 #include <asm/current.h>
 
-
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  * We make no fairness assumptions. They have a cost.
  */
 
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       int on_cpu;
-       int line_no;
-       void *previous;
-       struct task_struct * task;
-       const char *base_file;
-#endif
-} spinlock_t;
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPIN_LOCK_UNLOCKED     (spinlock_t){ 0, -1, 0, NULL, NULL, NULL }
-#else
-#define SPIN_LOCK_UNLOCKED     (spinlock_t){ 0 }
-#endif
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define spin_unlock_wait(x)    do { barrier(); } while ((x)->lock)
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-extern void _raw_spin_unlock(spinlock_t * lock);
-extern void debug_spin_lock(spinlock_t * lock, const char *, int);
-extern int debug_spin_trylock(spinlock_t * lock, const char *, int);
-#define _raw_spin_lock(LOCK) \
-       debug_spin_lock(LOCK, __BASE_FILE__, __LINE__)
-#define _raw_spin_trylock(LOCK) \
-       debug_spin_trylock(LOCK, __BASE_FILE__, __LINE__)
-#else
-static inline void _raw_spin_unlock(spinlock_t * lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_is_locked(x)        ((x)->lock != 0)
+#define __raw_spin_unlock_wait(x) \
+               do { cpu_relax(); } while ((x)->lock)
+
+static inline void __raw_spin_unlock(raw_spinlock_t * lock)
 {
        mb();
        lock->lock = 0;
 }
 
-static inline void _raw_spin_lock(spinlock_t * lock)
+static inline void __raw_spin_lock(raw_spinlock_t * lock)
 {
        long tmp;
 
@@ -70,80 +44,64 @@ static inline void _raw_spin_lock(spinlock_t * lock)
        : "m"(lock->lock) : "memory");
 }
 
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        return !test_and_set_bit(0, &lock->lock);
 }
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
 
 /***********************************************************/
 
-typedef struct {
-       volatile unsigned int lock;
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED       (rwlock_t){ 0 }
-
-#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-static inline int read_can_lock(rwlock_t *lock)
+static inline int __raw_read_can_lock(raw_rwlock_t *lock)
 {
        return (lock->lock & 1) == 0;
 }
 
-static inline int write_can_lock(rwlock_t *lock)
+static inline int __raw_write_can_lock(raw_rwlock_t *lock)
 {
        return lock->lock == 0;
 }
 
-#ifdef CONFIG_DEBUG_RWLOCK
-extern void _raw_write_lock(rwlock_t * lock);
-extern void _raw_read_lock(rwlock_t * lock);
-#else
-static inline void _raw_write_lock(rwlock_t * lock)
+static inline void __raw_read_lock(raw_rwlock_t *lock)
 {
        long regx;
 
        __asm__ __volatile__(
        "1:     ldl_l   %1,%0\n"
-       "       bne     %1,6f\n"
-       "       lda     %1,1\n"
+       "       blbs    %1,6f\n"
+       "       subl    %1,2,%1\n"
        "       stl_c   %1,%0\n"
        "       beq     %1,6f\n"
        "       mb\n"
        ".subsection 2\n"
        "6:     ldl     %1,%0\n"
-       "       bne     %1,6b\n"
+       "       blbs    %1,6b\n"
        "       br      1b\n"
        ".previous"
        : "=m" (*lock), "=&r" (regx)
        : "m" (*lock) : "memory");
 }
 
-static inline void _raw_read_lock(rwlock_t * lock)
+static inline void __raw_write_lock(raw_rwlock_t *lock)
 {
        long regx;
 
        __asm__ __volatile__(
        "1:     ldl_l   %1,%0\n"
-       "       blbs    %1,6f\n"
-       "       subl    %1,2,%1\n"
+       "       bne     %1,6f\n"
+       "       lda     %1,1\n"
        "       stl_c   %1,%0\n"
        "       beq     %1,6f\n"
        "       mb\n"
        ".subsection 2\n"
        "6:     ldl     %1,%0\n"
-       "       blbs    %1,6b\n"
+       "       bne     %1,6b\n"
        "       br      1b\n"
        ".previous"
        : "=m" (*lock), "=&r" (regx)
        : "m" (*lock) : "memory");
 }
-#endif /* CONFIG_DEBUG_RWLOCK */
 
-static inline int _raw_read_trylock(rwlock_t * lock)
+static inline int __raw_read_trylock(raw_rwlock_t * lock)
 {
        long regx;
        int success;
@@ -165,7 +123,7 @@ static inline int _raw_read_trylock(rwlock_t * lock)
        return success;
 }
 
-static inline int _raw_write_trylock(rwlock_t * lock)
+static inline int __raw_write_trylock(raw_rwlock_t * lock)
 {
        long regx;
        int success;
@@ -187,13 +145,7 @@ static inline int _raw_write_trylock(rwlock_t * lock)
        return success;
 }
 
-static inline void _raw_write_unlock(rwlock_t * lock)
-{
-       mb();
-       lock->lock = 0;
-}
-
-static inline void _raw_read_unlock(rwlock_t * lock)
+static inline void __raw_read_unlock(raw_rwlock_t * lock)
 {
        long regx;
        __asm__ __volatile__(
@@ -209,4 +161,10 @@ static inline void _raw_read_unlock(rwlock_t * lock)
        : "m" (*lock) : "memory");
 }
 
+static inline void __raw_write_unlock(raw_rwlock_t * lock)
+{
+       mb();
+       lock->lock = 0;
+}
+
 #endif /* _ALPHA_SPINLOCK_H */
diff --git a/include/asm-alpha/spinlock_types.h b/include/asm-alpha/spinlock_types.h
new file mode 100644 (file)
index 0000000..8141eb5
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _ALPHA_SPINLOCK_TYPES_H
+#define _ALPHA_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index 27d71e9d413b9f93c98cf690c298ac010bb61d7d..21c0e16dce5fe3d71721208e657aa9812a8cae1f 100644 (file)
@@ -66,3 +66,4 @@ struct pxafb_mach_info {
 
 };
 void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
+unsigned long pxafb_get_hsync_time(struct device *dev);
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
new file mode 100644 (file)
index 0000000..ac57bc8
--- /dev/null
@@ -0,0 +1,69 @@
+/* linux/include/asm/arch-s3c2410/fb.h
+ *
+ * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * Inspired by pxafb.h
+ *
+ * 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.
+ *
+ *
+ *  Changelog:
+ *     07-Sep-2004     RTP     Created file
+ *     03-Nov-2004     BJD     Updated and minor cleanups
+ *     03-Aug-2005     RTP     Renamed to fb.h
+*/
+
+#ifndef __ASM_ARM_FB_H
+#define __ASM_ARM_FB_H
+
+#include <asm/arch/regs-lcd.h>
+
+struct s3c2410fb_val {
+       unsigned int    defval;
+       unsigned int    min;
+       unsigned int    max;
+};
+
+struct s3c2410fb_hw {
+       unsigned long   lcdcon1;
+       unsigned long   lcdcon2;
+       unsigned long   lcdcon3;
+       unsigned long   lcdcon4;
+       unsigned long   lcdcon5;
+};
+
+struct s3c2410fb_mach_info {
+       unsigned char   fixed_syncs;    /* do not update sync/border */
+
+       /* Screen size */
+       int             width;
+       int             height;
+
+       /* Screen info */
+       struct s3c2410fb_val xres;
+       struct s3c2410fb_val yres;
+       struct s3c2410fb_val bpp;
+
+       /* lcd configuration registers */
+       struct s3c2410fb_hw  regs;
+
+       /* GPIOs */
+
+       unsigned long   gpcup;
+       unsigned long   gpcup_mask;
+       unsigned long   gpccon;
+       unsigned long   gpccon_mask;
+       unsigned long   gpdup;
+       unsigned long   gpdup_mask;
+       unsigned long   gpdcon;
+       unsigned long   gpdcon_mask;
+
+       /* lpc3600 control register */
+       unsigned long   lpcsel;
+};
+
+void __init set_s3c2410fb_info(struct s3c2410fb_mach_info *hard_s3c2410fb_info);
+
+#endif /* __ASM_ARM_FB_H */
index 7f882ea92b2a760b8ac17c75be3720e3aa62c7ba..b6b1b4e8bbebf9bc7c8f23753b1817761da7e764 100644 (file)
 
 #define S3C2410_LCDCON1_ENVID     (1)
 
+#define S3C2410_LCDCON1_MODEMASK    0x1E
+
 #define S3C2410_LCDCON2_VBPD(x)            ((x) << 24)
 #define S3C2410_LCDCON2_LINEVAL(x)  ((x) << 14)
 #define S3C2410_LCDCON2_VFPD(x)            ((x) << 6)
 #define S3C2410_LCDCON2_VSPW(x)            ((x) << 0)
 
+#define S3C2410_LCDCON2_GET_VBPD(x) ( ((x) >> 24) & 0xFF)
+#define S3C2410_LCDCON2_GET_VFPD(x) ( ((x) >>  6) & 0xFF)
+#define S3C2410_LCDCON2_GET_VSPW(x) ( ((x) >>  0) & 0x3F)
+
 #define S3C2410_LCDCON3_HBPD(x)            ((x) << 19)
 #define S3C2410_LCDCON3_WDLY(x)            ((x) << 19)
 #define S3C2410_LCDCON3_HOZVAL(x)   ((x) << 8)
 #define S3C2410_LCDCON3_HFPD(x)            ((x) << 0)
 #define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
 
+#define S3C2410_LCDCON3_GET_HBPD(x) ( ((x) >> 19) & 0x7F)
+#define S3C2410_LCDCON3_GET_HFPD(x) ( ((x) >>  0) & 0xFF)
+
 #define S3C2410_LCDCON4_MVAL(x)            ((x) << 8)
 #define S3C2410_LCDCON4_HSPW(x)            ((x) << 0)
 #define S3C2410_LCDCON4_WLH(x)     ((x) << 0)
 
+#define S3C2410_LCDCON4_GET_HSPW(x) ( ((x) >>  0) & 0xFF)
+
 #define S3C2410_LCDCON5_BPP24BL            (1<<12)
 #define S3C2410_LCDCON5_FRM565     (1<<11)
 #define S3C2410_LCDCON5_INVVCLK            (1<<10)
 #define S3C2410_DITHMODE   S3C2410_LCDREG(0x4C)
 #define S3C2410_TPAL      S3C2410_LCDREG(0x50)
 
+#define S3C2410_TPAL_EN                (1<<24)
+
 /* interrupt info */
 #define S3C2410_LCDINTPND  S3C2410_LCDREG(0x54)
 #define S3C2410_LCDSRCPND  S3C2410_LCDREG(0x58)
 #define S3C2410_LCDINTMSK  S3C2410_LCDREG(0x5C)
+#define S3C2410_LCDINT_FIWSEL  (1<<2)
+#define        S3C2410_LCDINT_FRSYNC   (1<<1)
+#define S3C2410_LCDINT_FICNT   (1<<0)
+
 #define S3C2410_LPCSEL    S3C2410_LCDREG(0x60)
 
 #define S3C2410_TFTPAL(x)  S3C2410_LCDREG((0x400 + (x)*4))
index 1f906d09b6880f2ac04e9bb0dedf3dd0eafdafee..cb4906b4555583d36c0b3b91f94d2d9d9a4724c4 100644 (file)
  * Unlocked value: 0
  * Locked value: 1
  */
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
 
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0 }
+#define __raw_spin_is_locked(x)                ((x)->lock != 0)
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
 
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while (0)
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define spin_unlock_wait(x)    do { barrier(); } while (spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
        unsigned long tmp;
 
@@ -47,7 +40,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
        smp_mb();
 }
 
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        unsigned long tmp;
 
@@ -67,7 +60,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
        }
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        smp_mb();
 
@@ -80,23 +73,14 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
 
 /*
  * RWLOCKS
- */
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED       (rwlock_t) { 0 }
-#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while (0)
-#define rwlock_is_locked(x)    (*((volatile unsigned int *)(x)) != 0)
-
-/*
+ *
+ *
  * Write locks are easy - we just set bit 31.  When unlocking, we can
  * just write zero since the lock is exclusively held.
  */
-static inline void _raw_write_lock(rwlock_t *rw)
+#define rwlock_is_locked(x)    (*((volatile unsigned int *)(x)) != 0)
+
+static inline void __raw_write_lock(rwlock_t *rw)
 {
        unsigned long tmp;
 
@@ -113,7 +97,7 @@ static inline void _raw_write_lock(rwlock_t *rw)
        smp_mb();
 }
 
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(rwlock_t *rw)
 {
        unsigned long tmp;
 
@@ -133,7 +117,7 @@ static inline int _raw_write_trylock(rwlock_t *rw)
        }
 }
 
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
        smp_mb();
 
@@ -156,7 +140,7 @@ static inline void _raw_write_unlock(rwlock_t *rw)
  * currently active.  However, we know we won't have any write
  * locks.
  */
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
        unsigned long tmp, tmp2;
 
@@ -173,7 +157,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
        smp_mb();
 }
 
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(rwlock_t *rw)
 {
        unsigned long tmp, tmp2;
 
@@ -190,6 +174,6 @@ static inline void _raw_read_unlock(rwlock_t *rw)
        : "cc");
 }
 
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
 #endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-arm/spinlock_types.h b/include/asm-arm/spinlock_types.h
new file mode 100644 (file)
index 0000000..43e83f6
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index 278de61224d1c82ca667ebee87f62a536bc06986..c49df635a80f11e6d5202152dee10a30cb6f5cc7 100644 (file)
 #define __NR_inotify_init              (__NR_SYSCALL_BASE+316)
 #define __NR_inotify_add_watch         (__NR_SYSCALL_BASE+317)
 #define __NR_inotify_rm_watch          (__NR_SYSCALL_BASE+318)
+#define __NR_mbind                     (__NR_SYSCALL_BASE+319)
+#define __NR_get_mempolicy             (__NR_SYSCALL_BASE+320)
+#define __NR_set_mempolicy             (__NR_SYSCALL_BASE+321)
 
 /*
  * The following SWIs are ARM private.
index 791ee1da9bfa0f81a0e320c872a1fbebe520a81d..dc28daab8aa8d7786fa619facc0116480c33858e 100644 (file)
@@ -22,8 +22,6 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-#define irq_enter()            (preempt_count() += HARDIRQ_OFFSET)
-
 #ifndef CONFIG_SMP
 
 extern asmlinkage void __do_softirq(void);
index faff403e1061562f77e6c7a13f7c46d6775bb257..7d0298347ee7df599088ca5cbb6a4f0c8ee2947b 100644 (file)
  * and page free order so much..
  */
 #ifdef CONFIG_SMP
-  #define FREE_PTE_NR  506
+  #ifdef ARCH_FREE_PTR_NR
+    #define FREE_PTR_NR   ARCH_FREE_PTR_NR
+  #else
+    #define FREE_PTE_NR        506
+  #endif
   #define tlb_fast_mode(tlb) ((tlb)->nr == ~0U)
 #else
   #define FREE_PTE_NR  1
index 6f857be2b6447ac3f64f134ce45844ef2555b11b..a9c55490fb8238e78584176bdb6002a6bd38432e 100644 (file)
                VMLINUX_SYMBOL(__kprobes_text_start) = .;               \
                *(.kprobes.text)                                        \
                VMLINUX_SYMBOL(__kprobes_text_end) = .;
+
+               /* DWARF debug sections.
+               Symbols in the DWARF debugging sections are relative to
+               the beginning of the section so we begin them at 0.  */
+#define DWARF_DEBUG                                                    \
+               /* DWARF 1 */                                           \
+               .debug          0 : { *(.debug) }                       \
+               .line           0 : { *(.line) }                        \
+               /* GNU DWARF 1 extensions */                            \
+               .debug_srcinfo  0 : { *(.debug_srcinfo) }               \
+               .debug_sfnames  0 : { *(.debug_sfnames) }               \
+               /* DWARF 1.1 and DWARF 2 */                             \
+               .debug_aranges  0 : { *(.debug_aranges) }               \
+               .debug_pubnames 0 : { *(.debug_pubnames) }              \
+               /* DWARF 2 */                                           \
+               .debug_info     0 : { *(.debug_info                     \
+                               .gnu.linkonce.wi.*) }                   \
+               .debug_abbrev   0 : { *(.debug_abbrev) }                \
+               .debug_line     0 : { *(.debug_line) }                  \
+               .debug_frame    0 : { *(.debug_frame) }                 \
+               .debug_str      0 : { *(.debug_str) }                   \
+               .debug_loc      0 : { *(.debug_loc) }                   \
+               .debug_macinfo  0 : { *(.debug_macinfo) }               \
+               /* SGI/MIPS DWARF 2 extensions */                       \
+               .debug_weaknames 0 : { *(.debug_weaknames) }            \
+               .debug_funcnames 0 : { *(.debug_funcnames) }            \
+               .debug_typenames 0 : { *(.debug_typenames) }            \
+               .debug_varnames  0 : { *(.debug_varnames) }             \
+
+               /* Stabs debugging sections.  */
+#define STABS_DEBUG                                                    \
+               .stab 0 : { *(.stab) }                                  \
+               .stabstr 0 : { *(.stabstr) }                            \
+               .stab.excl 0 : { *(.stab.excl) }                        \
+               .stab.exclstr 0 : { *(.stab.exclstr) }                  \
+               .stab.index 0 : { *(.stab.index) }                      \
+               .stab.indexstr 0 : { *(.stab.indexstr) }                \
+               .comment 0 : { *(.comment) }
index 6a1b1882285c004a1c5f80b109c046fe483c8bee..8c454aa58ac6b157441ad2a77f9211e4a30f882e 100644 (file)
@@ -130,6 +130,8 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC 2
 #define NMI_INVALID    3
 
+extern int disable_timer_pin_1;
+
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 
index 28ed8b296afc137af6b3043179fc97eb230a2f54..75c67c785bb8dfd5ddcebf1e07579b5270db2a7c 100644 (file)
@@ -35,7 +35,7 @@
  */
 #define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)
 
-extern inline long
+static inline long
 div_ll_X_l_rem(long long divs, long div, long *rem)
 {
        long dum2;
index 521e227db679f460b34da67e94e303f34ec69fb9..06ae4d81ba6a6d3421e7a95ca23e1c34dce4668c 100644 (file)
@@ -22,7 +22,15 @@ static inline void mach_reboot(void)
        for (i = 0; i < 100; i++) {
                kb_wait();
                udelay(50);
-               outb(0xfe, 0x64);         /* pulse reset low */
+               outb(0x60, 0x64);       /* write Controller Command Byte */
+               udelay(50);
+               kb_wait();
+               udelay(50);
+               outb(0x14, 0x60);       /* set "System flag" */
+               udelay(50);
+               kb_wait();
+               udelay(50);
+               outb(0xfe, 0x64);       /* pulse reset low */
                udelay(50);
        }
 }
index 516421300ea2d2346cfb084eefb276bd00b9ec18..348fe3a4879dd366ff30a40f774b018aa73eb6a2 100644 (file)
@@ -29,7 +29,7 @@ static inline void get_memcfg_numa(void)
 #ifdef CONFIG_X86_NUMAQ
        if (get_memcfg_numaq())
                return;
-#elif CONFIG_ACPI_SRAT
+#elif defined(CONFIG_ACPI_SRAT)
        if (get_memcfg_from_srat())
                return;
 #endif
diff --git a/include/asm-i386/numa.h b/include/asm-i386/numa.h
new file mode 100644 (file)
index 0000000..96fcb15
--- /dev/null
@@ -0,0 +1,3 @@
+
+int pxm_to_nid(int pxm);
+
index 37bef8ed7bed12bd33bf3670ccf7991516aa7484..0a4ec764377ca1aa0db8c607a35e9ddfd586d297 100644 (file)
@@ -679,7 +679,7 @@ static inline void rep_nop(void)
    However we don't do prefetches for pre XP Athlons currently
    That should be fixed. */
 #define ARCH_HAS_PREFETCH
-extern inline void prefetch(const void *x)
+static inline void prefetch(const void *x)
 {
        alternative_input(ASM_NOP4,
                          "prefetchnta (%1)",
@@ -693,7 +693,7 @@ extern inline void prefetch(const void *x)
 
 /* 3dnow! prefetch to get an exclusive cache line. Useful for 
    spinlocks to avoid one state transition in the cache coherency protocol. */
-extern inline void prefetchw(const void *x)
+static inline void prefetchw(const void *x)
 {
        alternative_input(ASM_NOP4,
                          "prefetchw (%1)",
index f9ff31f400369f0e1429f72829d95f6738e7a129..23604350cdf45e25df90180afa2985f9b489dfd1 100644 (file)
@@ -7,46 +7,21 @@
 #include <linux/config.h>
 #include <linux/compiler.h>
 
-asmlinkage int printk(const char * fmt, ...)
-       __attribute__ ((format (printf, 1, 2)));
-
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
-       volatile unsigned int slock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC_INIT    , SPINLOCK_MAGIC
-#else
-#define SPINLOCK_MAGIC_INIT    /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
+ *
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  *
  * We make no fairness assumptions. They have a cost.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
  */
 
-#define spin_is_locked(x)      (*(volatile signed char *)(&(x)->slock) <= 0)
-#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
+#define __raw_spin_is_locked(x) \
+               (*(volatile signed char *)(&(x)->slock) <= 0)
 
-#define spin_lock_string \
+#define __raw_spin_lock_string \
        "\n1:\t" \
        "lock ; decb %0\n\t" \
        "jns 3f\n" \
@@ -57,7 +32,7 @@ typedef struct {
        "jmp 1b\n" \
        "3:\n\t"
 
-#define spin_lock_string_flags \
+#define __raw_spin_lock_string_flags \
        "\n1:\t" \
        "lock ; decb %0\n\t" \
        "jns 4f\n\t" \
@@ -73,86 +48,71 @@ typedef struct {
        "jmp 1b\n" \
        "4:\n\t"
 
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+       __asm__ __volatile__(
+               __raw_spin_lock_string
+               :"=m" (lock->slock) : : "memory");
+}
+
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
+{
+       __asm__ __volatile__(
+               __raw_spin_lock_string_flags
+               :"=m" (lock->slock) : "r" (flags) : "memory");
+}
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+       char oldval;
+       __asm__ __volatile__(
+               "xchgb %b0,%1"
+               :"=q" (oldval), "=m" (lock->slock)
+               :"0" (0) : "memory");
+       return oldval > 0;
+}
+
 /*
- * This works. Despite all the confusion.
- * (except on PPro SMP or if we are using OOSTORE)
+ * __raw_spin_unlock based on writing $1 to the low byte.
+ * This method works. Despite all the confusion.
+ * (except on PPro SMP or if we are using OOSTORE, so we use xchgb there)
  * (PPro errata 66, 92)
  */
 
 #if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
 
-#define spin_unlock_string \
+#define __raw_spin_unlock_string \
        "movb $1,%0" \
                :"=m" (lock->slock) : : "memory"
 
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(lock->magic != SPINLOCK_MAGIC);
-       BUG_ON(!spin_is_locked(lock));
-#endif
        __asm__ __volatile__(
-               spin_unlock_string
+               __raw_spin_unlock_string
        );
 }
 
 #else
 
-#define spin_unlock_string \
+#define __raw_spin_unlock_string \
        "xchgb %b0, %1" \
                :"=q" (oldval), "=m" (lock->slock) \
                :"0" (oldval) : "memory"
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        char oldval = 1;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(lock->magic != SPINLOCK_MAGIC);
-       BUG_ON(!spin_is_locked(lock));
-#endif
-       __asm__ __volatile__(
-               spin_unlock_string
-       );
-}
 
-#endif
-
-static inline int _raw_spin_trylock(spinlock_t *lock)
-{
-       char oldval;
        __asm__ __volatile__(
-               "xchgb %b0,%1"
-               :"=q" (oldval), "=m" (lock->slock)
-               :"0" (0) : "memory");
-       return oldval > 0;
+               __raw_spin_unlock_string
+       );
 }
 
-static inline void _raw_spin_lock(spinlock_t *lock)
-{
-#ifdef CONFIG_DEBUG_SPINLOCK
-       if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-               printk("eip: %p\n", __builtin_return_address(0));
-               BUG();
-       }
 #endif
-       __asm__ __volatile__(
-               spin_lock_string
-               :"=m" (lock->slock) : : "memory");
-}
 
-static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
-{
-#ifdef CONFIG_DEBUG_SPINLOCK
-       if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-               printk("eip: %p\n", __builtin_return_address(0));
-               BUG();
-       }
-#endif
-       __asm__ __volatile__(
-               spin_lock_string_flags
-               :"=m" (lock->slock) : "r" (flags) : "memory");
-}
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -163,72 +123,41 @@ static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
  * can "mix" irq-safe locks - any writer needs to get a
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
+ *
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ *
+ * Changed to use the same technique as rw semaphores.  See
+ * semaphore.h for details.  -ben
+ *
+ * the helpers are in arch/i386/kernel/semaphore.c
  */
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RWLOCK_MAGIC   0xdeaf1eed
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define RWLOCK_MAGIC_INIT      , RWLOCK_MAGIC
-#else
-#define RWLOCK_MAGIC_INIT      /* */
-#endif
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 
 /**
  * read_can_lock - would read_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define read_can_lock(x) ((int)(x)->lock > 0)
+#define __raw_read_can_lock(x)         ((int)(x)->lock > 0)
 
 /**
  * write_can_lock - would write_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
+#define __raw_write_can_lock(x)                ((x)->lock == RW_LOCK_BIAS)
 
-/*
- * On x86, we implement read-write locks as a 32-bit counter
- * with the high bit (sign) being the "contended" bit.
- *
- * The inline assembly is non-obvious. Think about it.
- *
- * Changed to use the same technique as rw semaphores.  See
- * semaphore.h for details.  -ben
- */
-/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
-
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
        __build_read_lock(rw, "__read_lock_failed");
 }
 
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
        __build_write_lock(rw, "__write_lock_failed");
 }
 
-#define _raw_read_unlock(rw)           asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
-#define _raw_write_unlock(rw)  asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
-
-static inline int _raw_read_trylock(rwlock_t *lock)
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
 {
        atomic_t *count = (atomic_t *)lock;
        atomic_dec(count);
@@ -238,7 +167,7 @@ static inline int _raw_read_trylock(rwlock_t *lock)
        return 0;
 }
 
-static inline int _raw_write_trylock(rwlock_t *lock)
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
 {
        atomic_t *count = (atomic_t *)lock;
        if (atomic_sub_and_test(RW_LOCK_BIAS, count))
@@ -247,4 +176,15 @@ static inline int _raw_write_trylock(rwlock_t *lock)
        return 0;
 }
 
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+       asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+       asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
+                                : "=m" (rw->lock) : : "memory");
+}
+
 #endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-i386/spinlock_types.h b/include/asm-i386/spinlock_types.h
new file mode 100644 (file)
index 0000000..59efe84
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 1 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { RW_LOCK_BIAS }
+
+#endif
index e2cb9fa6f563db415e494dae49b0173fa3e2b7c6..8fbf791651bf84cfaf8e2bbb3396e76b13c87517 100644 (file)
@@ -48,7 +48,7 @@ struct thread_info {
 
 #else /* !__ASSEMBLY__ */
 
-#include <asm/asm_offsets.h>
+#include <asm/asm-offsets.h>
 
 #endif
 
index 2461b731781ebc182fd7b70c534b6dd87bb15e76..0ec27c9e8e45ba696be1a06a81df49d27d222729 100644 (file)
@@ -60,7 +60,7 @@ static inline int node_to_first_cpu(int node)
        return first_cpu(mask);
 }
 
-#define pcibus_to_node(bus) mp_bus_id_to_node[(bus)->number]
+#define pcibus_to_node(bus) ((long) (bus)->sysdata)
 #define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus))
 
 /* sched_domains SD_NODE_INIT for NUMAQ machines */
index a7cb377745bf01968d49984ade8d57fcd27369dd..fbaf90a3968c1f7c4f5bd11b818a604c625e8923 100644 (file)
@@ -332,7 +332,7 @@ type name(type1 arg1) \
 long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1))); \
+       : "0" (__NR_##name),"b" ((long)(arg1)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -342,7 +342,7 @@ type name(type1 arg1,type2 arg2) \
 long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
-       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
+       : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -353,7 +353,7 @@ long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-                 "d" ((long)(arg3))); \
+                 "d" ((long)(arg3)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -364,7 +364,7 @@ long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4))); \
+         "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \
 __syscall_return(type,__res); \
 } 
 
@@ -376,7 +376,7 @@ long __res; \
 __asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
-         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
+         "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
@@ -389,7 +389,7 @@ __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; p
        : "=a" (__res) \
        : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
          "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
-         "0" ((long)(arg6))); \
+         "0" ((long)(arg6)) : "memory"); \
 __syscall_return(type,__res); \
 }
 
index 149ad01184550b70f38fabc3e9763dc9d51b4003..97a28b8b2dddd98028b3ccfca697c1f42338313f 100644 (file)
@@ -11,8 +11,6 @@
 #ifndef _ASM_IA64_MCA_H
 #define _ASM_IA64_MCA_H
 
-#define IA64_MCA_STACK_SIZE    8192
-
 #if !defined(__ASSEMBLY__)
 
 #include <linux/interrupt.h>
@@ -48,7 +46,8 @@ typedef union cmcv_reg_u {
 
 enum {
        IA64_MCA_RENDEZ_CHECKIN_NOTDONE =       0x0,
-       IA64_MCA_RENDEZ_CHECKIN_DONE    =       0x1
+       IA64_MCA_RENDEZ_CHECKIN_DONE    =       0x1,
+       IA64_MCA_RENDEZ_CHECKIN_INIT    =       0x2,
 };
 
 /* Information maintained by the MC infrastructure */
@@ -63,18 +62,42 @@ typedef struct ia64_mc_info_s {
 
 } ia64_mc_info_t;
 
-typedef struct ia64_mca_sal_to_os_state_s {
-       u64             imsto_os_gp;            /* GP of the os registered with the SAL */
-       u64             imsto_pal_proc;         /* PAL_PROC entry point - physical addr */
-       u64             imsto_sal_proc;         /* SAL_PROC entry point - physical addr */
-       u64             imsto_sal_gp;           /* GP of the SAL - physical */
-       u64             imsto_rendez_state;     /* Rendez state information */
-       u64             imsto_sal_check_ra;     /* Return address in SAL_CHECK while going
-                                                * back to SAL from OS after MCA handling.
-                                                */
-       u64             pal_min_state;          /* from PAL in r17 */
-       u64             proc_state_param;       /* from PAL in r18. See SDV 2:268 11.3.2.1 */
-} ia64_mca_sal_to_os_state_t;
+/* Handover state from SAL to OS and vice versa, for both MCA and INIT events.
+ * Besides the handover state, it also contains some saved registers from the
+ * time of the event.
+ * Note: mca_asm.S depends on the precise layout of this structure.
+ */
+
+struct ia64_sal_os_state {
+       /* SAL to OS, must be at offset 0 */
+       u64                     os_gp;                  /* GP of the os registered with the SAL, physical */
+       u64                     pal_proc;               /* PAL_PROC entry point, physical */
+       u64                     sal_proc;               /* SAL_PROC entry point, physical */
+       u64                     rv_rc;                  /* MCA - Rendezvous state, INIT - reason code */
+       u64                     proc_state_param;       /* from R18 */
+       u64                     monarch;                /* 1 for a monarch event, 0 for a slave */
+       /* common, must follow SAL to OS */
+       u64                     sal_ra;                 /* Return address in SAL, physical */
+       u64                     sal_gp;                 /* GP of the SAL - physical */
+       pal_min_state_area_t    *pal_min_state;         /* from R17.  physical in asm, virtual in C */
+       u64                     prev_IA64_KR_CURRENT;   /* previous value of IA64_KR(CURRENT) */
+       struct task_struct      *prev_task;             /* previous task, NULL if it is not useful */
+       /* Some interrupt registers are not saved in minstate, pt_regs or
+        * switch_stack.  Because MCA/INIT can occur when interrupts are
+        * disabled, we need to save the additional interrupt registers over
+        * MCA/INIT and resume.
+        */
+       u64                     isr;
+       u64                     ifa;
+       u64                     itir;
+       u64                     iipa;
+       u64                     iim;
+       u64                     iha;
+       /* OS to SAL, must follow common */
+       u64                     os_status;              /* OS status to SAL, enum below */
+       u64                     context;                /* 0 if return to same context
+                                                          1 if return to new context */
+};
 
 enum {
        IA64_MCA_CORRECTED      =       0x0,    /* Error has been corrected by OS_MCA */
@@ -83,36 +106,22 @@ enum {
        IA64_MCA_HALT           =       -3      /* System to be halted by SAL */
 };
 
+enum {
+       IA64_INIT_RESUME        =       0x0,    /* Resume after return from INIT */
+       IA64_INIT_WARM_BOOT     =       -1,     /* Warm boot of the system need from SAL */
+};
+
 enum {
        IA64_MCA_SAME_CONTEXT   =       0x0,    /* SAL to return to same context */
        IA64_MCA_NEW_CONTEXT    =       -1      /* SAL to return to new context */
 };
 
-typedef struct ia64_mca_os_to_sal_state_s {
-       u64             imots_os_status;        /*   OS status to SAL as to what happened
-                                                *   with the MCA handling.
-                                                */
-       u64             imots_sal_gp;           /* GP of the SAL - physical */
-       u64             imots_context;          /* 0 if return to same context
-                                                  1 if return to new context */
-       u64             *imots_new_min_state;   /* Pointer to structure containing
-                                                * new values of registers in the min state
-                                                * save area.
-                                                */
-       u64             imots_sal_check_ra;     /* Return address in SAL_CHECK while going
-                                                * back to SAL from OS after MCA handling.
-                                                */
-} ia64_mca_os_to_sal_state_t;
-
 /* Per-CPU MCA state that is too big for normal per-CPU variables.  */
 
 struct ia64_mca_cpu {
-       u64 stack[IA64_MCA_STACK_SIZE/8];       /* MCA memory-stack */
-       u64 proc_state_dump[512];
-       u64 stackframe[32];
-       u64 rbstore[IA64_MCA_STACK_SIZE/8];     /* MCA reg.-backing store */
+       u64 mca_stack[KERNEL_STACK_SIZE/8];
        u64 init_stack[KERNEL_STACK_SIZE/8];
-} __attribute__ ((aligned(16)));
+};
 
 /* Array of physical addresses of each CPU's MCA area.  */
 extern unsigned long __per_cpu_mca[NR_CPUS];
@@ -121,12 +130,29 @@ extern void ia64_mca_init(void);
 extern void ia64_mca_cpu_init(void *);
 extern void ia64_os_mca_dispatch(void);
 extern void ia64_os_mca_dispatch_end(void);
-extern void ia64_mca_ucmc_handler(void);
+extern void ia64_mca_ucmc_handler(struct pt_regs *, struct ia64_sal_os_state *);
+extern void ia64_init_handler(struct pt_regs *,
+                             struct switch_stack *,
+                             struct ia64_sal_os_state *);
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
 extern void ia64_mca_cmc_vector_setup(void);
-extern int  ia64_reg_MCA_extension(void*);
+extern int  ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *));
 extern void ia64_unreg_MCA_extension(void);
+extern u64 ia64_get_rnat(u64 *);
+
+#else  /* __ASSEMBLY__ */
+
+#define IA64_MCA_CORRECTED     0x0     /* Error has been corrected by OS_MCA */
+#define IA64_MCA_WARM_BOOT     -1      /* Warm boot of the system need from SAL */
+#define IA64_MCA_COLD_BOOT     -2      /* Cold boot of the system need from SAL */
+#define IA64_MCA_HALT          -3      /* System to be halted by SAL */
+
+#define IA64_INIT_RESUME       0x0     /* Resume after return from INIT */
+#define IA64_INIT_WARM_BOOT    -1      /* Warm boot of the system need from SAL */
+
+#define IA64_MCA_SAME_CONTEXT  0x0     /* SAL to return to same context */
+#define IA64_MCA_NEW_CONTEXT   -1      /* SAL to return to new context */
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_MCA_H */
index 836953e0f91f611977419855ece5debe3a1fc38b..27c9203d8ce3173bff55753e1882a651faf11bc6 100644 (file)
@@ -8,6 +8,8 @@
  * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 2002 Intel Corp.
  * Copyright (C) 2002 Jenna Hall <jenna.s.hall@intel.com>
+ * Copyright (C) 2005 Silicon Graphics, Inc
+ * Copyright (C) 2005 Keith Owens <kaos@sgi.com>
  */
 #ifndef _ASM_IA64_MCA_ASM_H
 #define _ASM_IA64_MCA_ASM_H
        ;;
 
 /*
- * The following offsets capture the order in which the
- * RSE related registers from the old context are
- * saved onto the new stack frame.
+ * The MCA and INIT stacks in struct ia64_mca_cpu look like normal kernel
+ * stacks, except that the SAL/OS state and a switch_stack are stored near the
+ * top of the MCA/INIT stack.  To support concurrent entry to MCA or INIT, as
+ * well as MCA over INIT, each event needs its own SAL/OS state.  All entries
+ * are 16 byte aligned.
  *
- *     +-----------------------+
- *     |NDIRTY [BSP - BSPSTORE]|
- *     +-----------------------+
- *     |       RNAT            |
- *     +-----------------------+
- *     |       BSPSTORE        |
- *     +-----------------------+
- *     |       IFS             |
- *     +-----------------------+
- *     |       PFS             |
- *     +-----------------------+
- *     |       RSC             |
- *     +-----------------------+ <-------- Bottom of new stack frame
+ *      +---------------------------+
+ *      |          pt_regs          |
+ *      +---------------------------+
+ *      |        switch_stack       |
+ *      +---------------------------+
+ *      |        SAL/OS state       |
+ *      +---------------------------+
+ *      |    16 byte scratch area   |
+ *      +---------------------------+ <-------- SP at start of C MCA handler
+ *      |           .....           |
+ *      +---------------------------+
+ *      | RBS for MCA/INIT handler  |
+ *      +---------------------------+
+ *      | struct task for MCA/INIT  |
+ *      +---------------------------+ <-------- Bottom of MCA/INIT stack
  */
-#define  rse_rsc_offset                0
-#define  rse_pfs_offset                (rse_rsc_offset+0x08)
-#define  rse_ifs_offset                (rse_pfs_offset+0x08)
-#define  rse_bspstore_offset   (rse_ifs_offset+0x08)
-#define  rse_rnat_offset       (rse_bspstore_offset+0x08)
-#define  rse_ndirty_offset     (rse_rnat_offset+0x08)
 
-/*
- * rse_switch_context
- *
- *     1. Save old RSC onto the new stack frame
- *     2. Save PFS onto new stack frame
- *     3. Cover the old frame and start a new frame.
- *     4. Save IFS onto new stack frame
- *     5. Save the old BSPSTORE on the new stack frame
- *     6. Save the old RNAT on the new stack frame
- *     7. Write BSPSTORE with the new backing store pointer
- *     8. Read and save the new BSP to calculate the #dirty registers
- * NOTE: Look at pages 11-10, 11-11 in PRM Vol 2
- */
-#define rse_switch_context(temp,p_stackframe,p_bspstore)                       \
-       ;;                                                                      \
-       mov     temp=ar.rsc;;                                                   \
-       st8     [p_stackframe]=temp,8;;                                 \
-       mov     temp=ar.pfs;;                                                   \
-       st8     [p_stackframe]=temp,8;                                          \
-       cover ;;                                                                \
-       mov     temp=cr.ifs;;                                                   \
-       st8     [p_stackframe]=temp,8;;                                         \
-       mov     temp=ar.bspstore;;                                              \
-       st8     [p_stackframe]=temp,8;;                                 \
-       mov     temp=ar.rnat;;                                                  \
-       st8     [p_stackframe]=temp,8;                                          \
-       mov     ar.bspstore=p_bspstore;;                                        \
-       mov     temp=ar.bsp;;                                                   \
-       sub     temp=temp,p_bspstore;;                                          \
-       st8     [p_stackframe]=temp,8;;
-
-/*
- * rse_return_context
- *     1. Allocate a zero-sized frame
- *     2. Store the number of dirty registers RSC.loadrs field
- *     3. Issue a loadrs to insure that any registers from the interrupted
- *        context which were saved on the new stack frame have been loaded
- *        back into the stacked registers
- *     4. Restore BSPSTORE
- *     5. Restore RNAT
- *     6. Restore PFS
- *     7. Restore IFS
- *     8. Restore RSC
- *     9. Issue an RFI
- */
-#define rse_return_context(psr_mask_reg,temp,p_stackframe)                     \
-       ;;                                                                      \
-       alloc   temp=ar.pfs,0,0,0,0;                                            \
-       add     p_stackframe=rse_ndirty_offset,p_stackframe;;                   \
-       ld8     temp=[p_stackframe];;                                           \
-       shl     temp=temp,16;;                                                  \
-       mov     ar.rsc=temp;;                                                   \
-       loadrs;;                                                                \
-       add     p_stackframe=-rse_ndirty_offset+rse_bspstore_offset,p_stackframe;;\
-       ld8     temp=[p_stackframe];;                                           \
-       mov     ar.bspstore=temp;;                                              \
-       add     p_stackframe=-rse_bspstore_offset+rse_rnat_offset,p_stackframe;;\
-       ld8     temp=[p_stackframe];;                                           \
-       mov     ar.rnat=temp;;                                                  \
-       add     p_stackframe=-rse_rnat_offset+rse_pfs_offset,p_stackframe;;     \
-       ld8     temp=[p_stackframe];;                                           \
-       mov     ar.pfs=temp;;                                                   \
-       add     p_stackframe=-rse_pfs_offset+rse_ifs_offset,p_stackframe;;      \
-       ld8     temp=[p_stackframe];;                                           \
-       mov     cr.ifs=temp;;                                                   \
-       add     p_stackframe=-rse_ifs_offset+rse_rsc_offset,p_stackframe;;      \
-       ld8     temp=[p_stackframe];;                                           \
-       mov     ar.rsc=temp ;                                                   \
-       mov     temp=psr;;                                                      \
-       or      temp=temp,psr_mask_reg;;                                        \
-       mov     cr.ipsr=temp;;                                                  \
-       mov     temp=ip;;                                                       \
-       add     temp=0x30,temp;;                                                \
-       mov     cr.iip=temp;;                                                   \
-       srlz.i;;                                                                \
-       rfi;;
+#define ALIGN16(x)                     ((x)&~15)
+#define MCA_PT_REGS_OFFSET             ALIGN16(KERNEL_STACK_SIZE-IA64_PT_REGS_SIZE)
+#define MCA_SWITCH_STACK_OFFSET                ALIGN16(MCA_PT_REGS_OFFSET-IA64_SWITCH_STACK_SIZE)
+#define MCA_SOS_OFFSET                 ALIGN16(MCA_SWITCH_STACK_OFFSET-IA64_SAL_OS_STATE_SIZE)
+#define MCA_SP_OFFSET                  ALIGN16(MCA_SOS_OFFSET-16)
 
 #endif /* _ASM_IA64_MCA_ASM_H */
index 0bef19538406f2b4e89e07d18809c3e985592eb0..fc544929ac34f6bdbed78f489a2aca5f7b024d57 100644 (file)
@@ -57,7 +57,7 @@
 #include <linux/config.h>
 
 #include <asm/fpu.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 
 /*
  * Base-2 logarithm of number of pages to allocate per task structure
@@ -119,7 +119,7 @@ struct pt_regs {
        unsigned long ar_unat;          /* interrupted task's NaT register (preserved) */
        unsigned long ar_pfs;           /* prev function state  */
        unsigned long ar_rsc;           /* RSE configuration */
-       /* The following two are valid only if cr_ipsr.cpl > 0: */
+       /* The following two are valid only if cr_ipsr.cpl > 0 || ti->flags & _TIF_MCA_INIT */
        unsigned long ar_rnat;          /* RSE NaT */
        unsigned long ar_bspstore;      /* RSE bspstore */
 
diff --git a/include/asm-ia64/sn/sn_feature_sets.h b/include/asm-ia64/sn/sn_feature_sets.h
new file mode 100644 (file)
index 0000000..e68a808
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef _ASM_IA64_SN_FEATURE_SETS_H
+#define _ASM_IA64_SN_FEATURE_SETS_H
+
+/*
+ * SN PROM Features
+ *
+ * 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) 2005 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+
+#include <asm/types.h>
+#include <asm/bitops.h>
+
+/* --------------------- PROM Features -----------------------------*/
+extern int sn_prom_feature_available(int id);
+
+#define MAX_PROM_FEATURE_SETS                  2
+
+/*
+ * The following defines features that may or may not be supported by the
+ * current PROM. The OS uses sn_prom_feature_available(feature) to test for
+ * the presence of a PROM feature. Down rev (old) PROMs will always test
+ * "false" for new features.
+ *
+ * Use:
+ *             if (sn_prom_feature_available(PRF_FEATURE_XXX))
+ *                     ...
+ */
+
+/*
+ * Example: feature XXX
+ */
+#define PRF_FEATURE_XXX                0
+
+
+
+/* --------------------- OS Features -------------------------------*/
+
+/*
+ * The following defines OS features that are optionally present in
+ * the operating system.
+ * During boot, PROM is notified of these features via a series of calls:
+ *
+ *             ia64_sn_set_os_feature(feature1);
+ *
+ * Once enabled, a feature cannot be disabled.
+ *
+ * By default, features are disabled unless explicitly enabled.
+ */
+#define  OSF_MCA_SLV_TO_OS_INIT_SLV            0
+#define  OSF_FEAT_LOG_SBES                     1
+
+#endif /* _ASM_IA64_SN_FEATURE_SETS_H */
index e67825ad1930cee26dca3971b5c674f1e21c79e1..fea35b33d4e485f835cbfd678121f053f4a925f2 100644 (file)
@@ -80,6 +80,9 @@
 #define SN_SAL_RESERVED_DO_NOT_USE                0x02000062
 #define SN_SAL_IOIF_GET_PCI_TOPOLOGY              0x02000064
 
+#define  SN_SAL_GET_PROM_FEATURE_SET              0x02000065
+#define  SN_SAL_SET_OS_FEATURE_SET                0x02000066
+
 /*
  * Service-specific constants
  */
 /*
  * Error Handling Features
  */
-#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV    0x1
-#define SAL_ERR_FEAT_LOG_SBES                  0x2
+#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV    0x1     // obsolete
+#define SAL_ERR_FEAT_LOG_SBES                  0x2     // obsolete
 #define SAL_ERR_FEAT_MFR_OVERRIDE              0x4
 #define SAL_ERR_FEAT_SBE_THRESHOLD             0xffff0000
 
@@ -151,12 +154,6 @@ sn_sal_rev(void)
        return (u32)(systab->sal_b_rev_major << 8 | systab->sal_b_rev_minor);
 }
 
-/*
- * Specify the minimum PROM revsion required for this kernel.
- * Note that they're stored in hex format...
- */
-#define SN_SAL_MIN_VERSION     0x0404
-
 /*
  * Returns the master console nasid, if the call fails, return an illegal
  * value.
@@ -336,7 +333,7 @@ ia64_sn_plat_cpei_handler(void)
 }
 
 /*
- * Set Error Handling Features
+ * Set Error Handling Features (Obsolete)
  */
 static inline u64
 ia64_sn_plat_set_error_handling_features(void)
@@ -1052,4 +1049,25 @@ ia64_sn_is_fake_prom(void)
        return (rv.status == 0);
 }
 
+static inline int
+ia64_sn_get_prom_feature_set(int set, unsigned long *feature_set)
+{
+       struct ia64_sal_retval rv;
+
+       SAL_CALL_NOLOCK(rv, SN_SAL_GET_PROM_FEATURE_SET, set, 0, 0, 0, 0, 0, 0);
+       if (rv.status != 0)
+               return rv.status;
+       *feature_set = rv.v0;
+       return 0;
+}
+
+static inline int
+ia64_sn_set_os_feature(int feature)
+{
+       struct ia64_sal_retval rv;
+
+       SAL_CALL_NOLOCK(rv, SN_SAL_SET_OS_FEATURE_SET, feature, 0, 0, 0, 0, 0, 0);
+       return rv.status;
+}
+
 #endif /* _ASM_IA64_SN_SN_SAL_H */
index d2430aa0d49db76db4b6c771bc1eb9a9bc402d36..5b78611411c30e244a650b230aaae7c62ec5a6e9 100644 (file)
 #include <asm/intrinsics.h>
 #include <asm/system.h>
 
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED                     (spinlock_t) { 0 }
-#define spin_lock_init(x)                      ((x)->lock = 0)
+#define __raw_spin_lock_init(x)                        ((x)->lock = 0)
 
 #ifdef ASM_SUPPORTED
 /*
  * Try to get the lock.  If we fail to get the lock, make a non-standard call to
  * ia64_spinlock_contention().  We do not use a normal call because that would force all
- * callers of spin_lock() to be non-leaf routines.  Instead, ia64_spinlock_contention() is
- * carefully coded to touch only those registers that spin_lock() marks "clobbered".
+ * callers of __raw_spin_lock() to be non-leaf routines.  Instead, ia64_spinlock_contention() is
+ * carefully coded to touch only those registers that __raw_spin_lock() marks "clobbered".
  */
 
 #define IA64_SPINLOCK_CLOBBERS "ar.ccv", "ar.pfs", "p14", "p15", "r27", "r28", "r29", "r30", "b6", "memory"
 
 static inline void
-_raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+__raw_spin_lock_flags (raw_spinlock_t *lock, unsigned long flags)
 {
        register volatile unsigned int *ptr asm ("r31") = &lock->lock;
 
@@ -94,17 +86,17 @@ _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
 #endif
 }
 
-#define _raw_spin_lock(lock) _raw_spin_lock_flags(lock, 0)
+#define __raw_spin_lock(lock) __raw_spin_lock_flags(lock, 0)
 
 /* Unlock by doing an ordered store and releasing the cacheline with nta */
-static inline void _raw_spin_unlock(spinlock_t *x) {
+static inline void __raw_spin_unlock(raw_spinlock_t *x) {
        barrier();
        asm volatile ("st4.rel.nta [%0] = r0\n\t" :: "r"(x));
 }
 
 #else /* !ASM_SUPPORTED */
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-# define _raw_spin_lock(x)                                                             \
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+# define __raw_spin_lock(x)                                                            \
 do {                                                                                   \
        __u32 *ia64_spinlock_ptr = (__u32 *) (x);                                       \
        __u64 ia64_spinlock_val;                                                        \
@@ -117,29 +109,20 @@ do {                                                                                      \
                } while (ia64_spinlock_val);                                            \
        }                                                                               \
 } while (0)
-#define _raw_spin_unlock(x)    do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0)
+#define __raw_spin_unlock(x)   do { barrier(); ((raw_spinlock_t *) x)->lock = 0; } while (0)
 #endif /* !ASM_SUPPORTED */
 
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define _raw_spin_trylock(x)   (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
-#define spin_unlock_wait(x)    do { barrier(); } while ((x)->lock)
-
-typedef struct {
-       volatile unsigned int read_counter      : 24;
-       volatile unsigned int write_lock        :  8;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#define __raw_spin_is_locked(x)                ((x)->lock != 0)
+#define __raw_spin_trylock(x)          (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
 
-#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-#define read_can_lock(rw)      (*(volatile int *)(rw) >= 0)
-#define write_can_lock(rw)     (*(volatile int *)(rw) == 0)
+#define __raw_read_can_lock(rw)                (*(volatile int *)(rw) >= 0)
+#define __raw_write_can_lock(rw)       (*(volatile int *)(rw) == 0)
 
-#define _raw_read_lock(rw)                                                             \
+#define __raw_read_lock(rw)                                                            \
 do {                                                                                   \
-       rwlock_t *__read_lock_ptr = (rw);                                               \
+       raw_rwlock_t *__read_lock_ptr = (rw);                                           \
                                                                                        \
        while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, acq) < 0)) {          \
                ia64_fetchadd(-1, (int *) __read_lock_ptr, rel);                        \
@@ -148,14 +131,14 @@ do {                                                                                      \
        }                                                                               \
 } while (0)
 
-#define _raw_read_unlock(rw)                                   \
+#define __raw_read_unlock(rw)                                  \
 do {                                                           \
-       rwlock_t *__read_lock_ptr = (rw);                       \
+       raw_rwlock_t *__read_lock_ptr = (rw);                   \
        ia64_fetchadd(-1, (int *) __read_lock_ptr, rel);        \
 } while (0)
 
 #ifdef ASM_SUPPORTED
-#define _raw_write_lock(rw)                                                    \
+#define __raw_write_lock(rw)                                                   \
 do {                                                                           \
        __asm__ __volatile__ (                                                  \
                "mov ar.ccv = r0\n"                                             \
@@ -170,7 +153,7 @@ do {                                                                                \
                :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory");            \
 } while(0)
 
-#define _raw_write_trylock(rw)                                                 \
+#define __raw_write_trylock(rw)                                                        \
 ({                                                                             \
        register long result;                                                   \
                                                                                \
@@ -182,7 +165,7 @@ do {                                                                                \
        (result == 0);                                                          \
 })
 
-static inline void _raw_write_unlock(rwlock_t *x)
+static inline void __raw_write_unlock(raw_rwlock_t *x)
 {
        u8 *y = (u8 *)x;
        barrier();
@@ -191,7 +174,7 @@ static inline void _raw_write_unlock(rwlock_t *x)
 
 #else /* !ASM_SUPPORTED */
 
-#define _raw_write_lock(l)                                                             \
+#define __raw_write_lock(l)                                                            \
 ({                                                                                     \
        __u64 ia64_val, ia64_set_val = ia64_dep_mi(-1, 0, 31, 1);                       \
        __u32 *ia64_write_lock_ptr = (__u32 *) (l);                                     \
@@ -202,7 +185,7 @@ static inline void _raw_write_unlock(rwlock_t *x)
        } while (ia64_val);                                                             \
 })
 
-#define _raw_write_trylock(rw)                                         \
+#define __raw_write_trylock(rw)                                                \
 ({                                                                     \
        __u64 ia64_val;                                                 \
        __u64 ia64_set_val = ia64_dep_mi(-1, 0, 31,1);                  \
@@ -210,7 +193,7 @@ static inline void _raw_write_unlock(rwlock_t *x)
        (ia64_val == 0);                                                \
 })
 
-static inline void _raw_write_unlock(rwlock_t *x)
+static inline void __raw_write_unlock(raw_rwlock_t *x)
 {
        barrier();
        x->write_lock = 0;
@@ -218,6 +201,6 @@ static inline void _raw_write_unlock(rwlock_t *x)
 
 #endif /* !ASM_SUPPORTED */
 
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
 #endif /*  _ASM_IA64_SPINLOCK_H */
diff --git a/include/asm-ia64/spinlock_types.h b/include/asm-ia64/spinlock_types.h
new file mode 100644 (file)
index 0000000..474e46f
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _ASM_IA64_SPINLOCK_TYPES_H
+#define _ASM_IA64_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int read_counter      : 31;
+       volatile unsigned int write_lock        :  1;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0, 0 }
+
+#endif
index 33256db4a7cf1b0ad4f82cdcf935b0bd421a42ed..635235fa1e32606c5955653bed40d0a77cb4899c 100644 (file)
@@ -275,6 +275,7 @@ extern void ia64_load_extra (struct task_struct *task);
  */
 #define __ARCH_WANT_UNLOCKED_CTXSW
 
+#define ARCH_HAS_PREFETCH_SWITCH_STACK
 #define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
 
 void cpu_idle_wait(void);
index 7dc8951708a3880648a89038257719f0a23bfa83..cf4a950a0f4f0c367b05954adde90cab4574fe7c 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef _ASM_IA64_THREAD_INFO_H
 #define _ASM_IA64_THREAD_INFO_H
 
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 
@@ -76,6 +76,7 @@ struct thread_info {
 #define TIF_SIGDELAYED         5       /* signal delayed from MCA/INIT/NMI/PMI context */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17
+#define TIF_MCA_INIT           18      /* this task is processing MCA or INIT */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
@@ -85,6 +86,7 @@ struct thread_info {
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_SIGDELAYED        (1 << TIF_SIGDELAYED)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
+#define _TIF_MCA_INIT          (1 << TIF_MCA_INIT)
 
 /* "work to do on user-return" bits */
 #define TIF_ALLWORK_MASK       (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SIGDELAYED)
index 61426ad3ecdb8b988c033c592adbdc1fe963d88d..5df0276b0493eaa6354cbdd019b69d35b20440c5 100644 (file)
@@ -114,13 +114,6 @@ extern void unw_remove_unwind_table (void *handle);
  */
 extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t);
 
-/*
- * Prepare to unwind from interruption.  The pt-regs and switch-stack structures must have
- * be "adjacent" (no state modifications between pt-regs and switch-stack).
- */
-extern void unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t,
-                                       struct pt_regs *pt, struct switch_stack *sw);
-
 extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t,
                                 struct switch_stack *sw);
 
index 6608d8371c5084541c2d84cb95e0f1df12eeb8f8..7de7def28da97c651ef7aaebed4271905663e038 100644 (file)
 #include <asm/atomic.h>
 #include <asm/page.h>
 
-extern int printk(const char * fmt, ...)
-       __attribute__ ((format (printf, 1, 2)));
-
-#define RW_LOCK_BIAS            0x01000000
-#define RW_LOCK_BIAS_STR       "0x01000000"
-
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
-       volatile int slock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC_INIT    , SPINLOCK_MAGIC
-#else
-#define SPINLOCK_MAGIC_INIT    /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
+ *
+ * (the type definitions are in asm/spinlock_types.h)
+ *
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  *
  * We make no fairness assumptions. They have a cost.
  */
 
-#define spin_is_locked(x)      (*(volatile int *)(&(x)->slock) <= 0)
-#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x)                (*(volatile int *)(&(x)->slock) <= 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+               do { cpu_relax(); } while (__raw_spin_is_locked(x))
 
 /**
- * _raw_spin_trylock - Try spin lock and return a result
+ * __raw_spin_trylock - Try spin lock and return a result
  * @lock: Pointer to the lock variable
  *
- * _raw_spin_trylock() tries to get the lock and returns a result.
+ * __raw_spin_trylock() tries to get the lock and returns a result.
  * On the m32r, the result value is 1 (= Success) or 0 (= Failure).
  */
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        int oldval;
        unsigned long tmp1, tmp2;
@@ -78,7 +51,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
         * }
         */
        __asm__ __volatile__ (
-               "# spin_trylock                 \n\t"
+               "# __raw_spin_trylock           \n\t"
                "ldi    %1, #0;                 \n\t"
                "mvfc   %2, psw;                \n\t"
                "clrpsw #0x40 -> nop;           \n\t"
@@ -97,16 +70,10 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
        return (oldval > 0);
 }
 
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
        unsigned long tmp0, tmp1;
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-       if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-               printk("pc: %p\n", __builtin_return_address(0));
-               BUG();
-       }
-#endif
        /*
         * lock->slock :  =1 : unlock
         *             : <=0 : lock
@@ -118,7 +85,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
         * }
         */
        __asm__ __volatile__ (
-               "# spin_lock                    \n\t"
+               "# __raw_spin_lock              \n\t"
                ".fillinsn                      \n"
                "1:                             \n\t"
                "mvfc   %1, psw;                \n\t"
@@ -145,12 +112,8 @@ static inline void _raw_spin_lock(spinlock_t *lock)
        );
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(lock->magic != SPINLOCK_MAGIC);
-       BUG_ON(!spin_is_locked(lock));
-#endif
        mb();
        lock->slock = 1;
 }
@@ -164,59 +127,32 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
  * can "mix" irq-safe locks - any writer needs to get a
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
+ *
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "contended" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ *
+ * Changed to use the same technique as rw semaphores.  See
+ * semaphore.h for details.  -ben
  */
-typedef struct {
-       volatile int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RWLOCK_MAGIC   0xdeaf1eed
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define RWLOCK_MAGIC_INIT      , RWLOCK_MAGIC
-#else
-#define RWLOCK_MAGIC_INIT      /* */
-#endif
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 
 /**
  * read_can_lock - would read_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define read_can_lock(x) ((int)(x)->lock > 0)
+#define __raw_read_can_lock(x) ((int)(x)->lock > 0)
 
 /**
  * write_can_lock - would write_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
-
-/*
- * On x86, we implement read-write locks as a 32-bit counter
- * with the high bit (sign) being the "contended" bit.
- *
- * The inline assembly is non-obvious. Think about it.
- *
- * Changed to use the same technique as rw semaphores.  See
- * semaphore.h for details.  -ben
- */
-/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
+#define __raw_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
 
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
        unsigned long tmp0, tmp1;
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
        /*
         * rw->lock :  >0 : unlock
         *          : <=0 : lock
@@ -264,13 +200,10 @@ static inline void _raw_read_lock(rwlock_t *rw)
        );
 }
 
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
        unsigned long tmp0, tmp1, tmp2;
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
        /*
         * rw->lock :  =RW_LOCK_BIAS_STR : unlock
         *          : !=RW_LOCK_BIAS_STR : lock
@@ -320,7 +253,7 @@ static inline void _raw_write_lock(rwlock_t *rw)
        );
 }
 
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
        unsigned long tmp0, tmp1;
 
@@ -342,7 +275,7 @@ static inline void _raw_read_unlock(rwlock_t *rw)
        );
 }
 
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
        unsigned long tmp0, tmp1, tmp2;
 
@@ -366,9 +299,9 @@ static inline void _raw_write_unlock(rwlock_t *rw)
        );
 }
 
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
-static inline int _raw_write_trylock(rwlock_t *lock)
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
 {
        atomic_t *count = (atomic_t *)lock;
        if (atomic_sub_and_test(RW_LOCK_BIAS, count))
diff --git a/include/asm-m32r/spinlock_types.h b/include/asm-m32r/spinlock_types.h
new file mode 100644 (file)
index 0000000..7e9941c
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _ASM_M32R_SPINLOCK_TYPES_H
+#define _ASM_M32R_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 1 }
+
+typedef struct {
+       volatile int lock;
+} raw_rwlock_t;
+
+#define RW_LOCK_BIAS                   0x01000000
+#define RW_LOCK_BIAS_STR               "0x01000000"
+
+#define __RAW_RW_LOCK_UNLOCKED         { RW_LOCK_BIAS }
+
+#endif
index f95e32b4042545025f7b557e8984bcb2021facb8..c42f88a9b9f986d25b3f859d38b9f3794ff17378 100644 (file)
@@ -259,7 +259,7 @@ static __inline__ int __test_bit(int nr, const volatile unsigned long * addr)
 #define find_first_bit(addr, size) \
         find_next_bit((addr), (size), 0)
 
-static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (const void * addr, int size, int offset)
 {
        unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
        unsigned long result = offset & ~31UL;
index 92cf102c2534c0445ed581e74d451bce311ef104..294ec7583ac9149696314aaece0256746e595b18 100644 (file)
@@ -25,7 +25,8 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
  * better 64-bit) boundary
  */
 
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst,
+       int len, int sum);
 
 
 /*
@@ -35,8 +36,8 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
  * better 64-bit) boundary
  */
 
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
-                                               int len, int sum, int *csum_err);
+extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
+       unsigned char *dst, int len, int sum, int *csum_err);
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)  \
        csum_partial_copy((src), (dst), (len), (sum))
index d280d013da032c0e3992b98a5b01c2267791441e..e7878d0f7d7a57d94003a0c9788fc858cbec88e9 100644 (file)
 /*
  *     SDRAM configuration registers.
  */
-#ifdef CONFIG_M5271EVB
+#ifdef CONFIG_M5271
 #define        MCFSIM_DCR              0x40            /* SDRAM control */
 #define        MCFSIM_DACR0            0x48            /* SDRAM base address 0 */
 #define        MCFSIM_DMR0             0x4c            /* SDRAM address mask 0 */
 #define        MCFSIM_DACR1            0x50            /* SDRAM base address 1 */
 #define        MCFSIM_DMR1             0x54            /* SDRAM address mask 1 */
-#else
+#endif
+#ifdef CONFIG_M5275
 #define        MCFSIM_DMR              0x40            /* SDRAM mode */
 #define        MCFSIM_DCR              0x44            /* SDRAM control */
 #define        MCFSIM_DCFG1            0x48            /* SDRAM configuration 1 */
 #define        MCFSIM_DMR1             0x5c            /* SDRAM address mask 1 */
 #endif
 
+/*
+ *     GPIO pins setups to enable the UARTs.
+ */
+#ifdef CONFIG_M5271
+#define MCF_GPIO_PAR_UART      0x100048        /* PAR UART address */
+#define UART0_ENABLE_MASK      0x000f
+#define UART1_ENABLE_MASK      0x0ff0
+#define UART2_ENABLE_MASK      0x3000
+#endif
+#ifdef CONFIG_M5275
+#define MCF_GPIO_PAR_UART      0x10007c        /* PAR UART address */
+#define UART0_ENABLE_MASK      0x000f
+#define UART1_ENABLE_MASK      0x00f0
+#define UART2_ENABLE_MASK      0x3f00 
+#endif
+
 /****************************************************************************/
 #endif /* m527xsim_h */
index 371993a206acdc751d2727f435d88bade432963d..610774a17f70d86a00524fb1c1e88f99f9d484af 100644 (file)
 #define        MCFSIM_DACR1            0x50            /* SDRAM base address 1 */
 #define        MCFSIM_DMR1             0x54            /* SDRAM address mask 1 */
 
+/*
+ *     Derek Cheung - 6 Feb 2005
+ *             add I2C and QSPI register definition using Freescale's MCF5282
+ */
+/* set Port AS pin for I2C or UART */
+#define MCF5282_GPIO_PASPAR     (volatile u16 *) (MCF_IPSBAR + 0x00100056)
+
+/* Interrupt Mask Register Register Low */ 
+#define MCF5282_INTC0_IMRL      (volatile u32 *) (MCF_IPSBAR + 0x0C0C)
+/* Interrupt Control Register 7 */
+#define MCF5282_INTC0_ICR17     (volatile u8 *) (MCF_IPSBAR + 0x0C51)
+
+
+
+/*********************************************************************
+*
+* Inter-IC (I2C) Module
+*
+*********************************************************************/
+/* Read/Write access macros for general use */
+#define MCF5282_I2C_I2ADR       (volatile u8 *) (MCF_IPSBAR + 0x0300) // Address 
+#define MCF5282_I2C_I2FDR       (volatile u8 *) (MCF_IPSBAR + 0x0304) // Freq Divider
+#define MCF5282_I2C_I2CR        (volatile u8 *) (MCF_IPSBAR + 0x0308) // Control
+#define MCF5282_I2C_I2SR        (volatile u8 *) (MCF_IPSBAR + 0x030C) // Status
+#define MCF5282_I2C_I2DR        (volatile u8 *) (MCF_IPSBAR + 0x0310) // Data I/O
+
+/* Bit level definitions and macros */
+#define MCF5282_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
+
+#define MCF5282_I2C_I2FDR_IC(x)                         (((x)&0x3F))
+
+#define MCF5282_I2C_I2CR_IEN    (0x80) // I2C enable
+#define MCF5282_I2C_I2CR_IIEN   (0x40)  // interrupt enable
+#define MCF5282_I2C_I2CR_MSTA   (0x20)  // master/slave mode
+#define MCF5282_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
+#define MCF5282_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
+#define MCF5282_I2C_I2CR_RSTA   (0x04)  // repeat start
+
+#define MCF5282_I2C_I2SR_ICF    (0x80)  // data transfer bit
+#define MCF5282_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
+#define MCF5282_I2C_I2SR_IBB    (0x20)  // I2C bus busy
+#define MCF5282_I2C_I2SR_IAL    (0x10)  // aribitration lost
+#define MCF5282_I2C_I2SR_SRW    (0x04)  // slave read/write
+#define MCF5282_I2C_I2SR_IIF    (0x02)  // I2C interrupt
+#define MCF5282_I2C_I2SR_RXAK   (0x01)  // received acknowledge
+
+
+
+/*********************************************************************
+*
+* Queued Serial Peripheral Interface (QSPI) Module
+*
+*********************************************************************/
+/* Derek - 21 Feb 2005 */
+/* change to the format used in I2C */
+/* Read/Write access macros for general use */
+#define MCF5282_QSPI_QMR        MCF_IPSBAR + 0x0340
+#define MCF5282_QSPI_QDLYR      MCF_IPSBAR + 0x0344
+#define MCF5282_QSPI_QWR        MCF_IPSBAR + 0x0348
+#define MCF5282_QSPI_QIR        MCF_IPSBAR + 0x034C
+#define MCF5282_QSPI_QAR        MCF_IPSBAR + 0x0350
+#define MCF5282_QSPI_QDR        MCF_IPSBAR + 0x0354
+#define MCF5282_QSPI_QCR        MCF_IPSBAR + 0x0354
+
+/* Bit level definitions and macros */
+#define MCF5282_QSPI_QMR_MSTR                           (0x8000)
+#define MCF5282_QSPI_QMR_DOHIE                          (0x4000)
+#define MCF5282_QSPI_QMR_BITS_16                        (0x0000)
+#define MCF5282_QSPI_QMR_BITS_8                         (0x2000)
+#define MCF5282_QSPI_QMR_BITS_9                         (0x2400)
+#define MCF5282_QSPI_QMR_BITS_10                        (0x2800)
+#define MCF5282_QSPI_QMR_BITS_11                        (0x2C00)
+#define MCF5282_QSPI_QMR_BITS_12                        (0x3000)
+#define MCF5282_QSPI_QMR_BITS_13                        (0x3400)
+#define MCF5282_QSPI_QMR_BITS_14                        (0x3800)
+#define MCF5282_QSPI_QMR_BITS_15                        (0x3C00)
+#define MCF5282_QSPI_QMR_CPOL                           (0x0200)
+#define MCF5282_QSPI_QMR_CPHA                           (0x0100)
+#define MCF5282_QSPI_QMR_BAUD(x)                        (((x)&0x00FF))
+
+#define MCF5282_QSPI_QDLYR_SPE                          (0x80)
+#define MCF5282_QSPI_QDLYR_QCD(x)                       (((x)&0x007F)<<8)
+#define MCF5282_QSPI_QDLYR_DTL(x)                       (((x)&0x00FF))
+
+#define MCF5282_QSPI_QWR_HALT                           (0x8000)
+#define MCF5282_QSPI_QWR_WREN                           (0x4000)
+#define MCF5282_QSPI_QWR_WRTO                           (0x2000)
+#define MCF5282_QSPI_QWR_CSIV                           (0x1000)
+#define MCF5282_QSPI_QWR_ENDQP(x)                       (((x)&0x000F)<<8)
+#define MCF5282_QSPI_QWR_CPTQP(x)                       (((x)&0x000F)<<4)
+#define MCF5282_QSPI_QWR_NEWQP(x)                       (((x)&0x000F))
+
+#define MCF5282_QSPI_QIR_WCEFB                          (0x8000)
+#define MCF5282_QSPI_QIR_ABRTB                          (0x4000)
+#define MCF5282_QSPI_QIR_ABRTL                          (0x1000)
+#define MCF5282_QSPI_QIR_WCEFE                          (0x0800)
+#define MCF5282_QSPI_QIR_ABRTE                          (0x0400)
+#define MCF5282_QSPI_QIR_SPIFE                          (0x0100)
+#define MCF5282_QSPI_QIR_WCEF                           (0x0008)
+#define MCF5282_QSPI_QIR_ABRT                           (0x0004)
+#define MCF5282_QSPI_QIR_SPIF                           (0x0001)
+
+#define MCF5282_QSPI_QAR_ADDR(x)                        (((x)&0x003F))
+
+#define MCF5282_QSPI_QDR_COMMAND(x)                     (((x)&0xFF00))
+#define MCF5282_QSPI_QCR_DATA(x)                        (((x)&0x00FF)<<8)
+#define MCF5282_QSPI_QCR_CONT                           (0x8000)
+#define MCF5282_QSPI_QCR_BITSE                          (0x4000)
+#define MCF5282_QSPI_QCR_DT                             (0x2000)
+#define MCF5282_QSPI_QCR_DSCK                           (0x1000)
+#define MCF5282_QSPI_QCR_CS                             (((x)&0x000F)<<8)
+
 /****************************************************************************/
 #endif /* m528xsim_h */
index bdd8c53ef34ce171ca6117a5c99f6f6948316e77..b17cd920977f592c7a05f5fdae337039fb784a66 100644 (file)
@@ -33,7 +33,7 @@
 .endm
 #endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
 
-#if defined(CONFIG_M527x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
 /*
  *     New version 2 cores have a configurable split cache arrangement.
  *     For now I am just enabling instruction cache - but ultimately I
        movec   %d0,%CACR               /* enable cache */
        nop
 .endm
-#endif /* CONFIG_M527x */
+#endif /* CONFIG_M523x || CONFIG_M527x */
 
 #if defined(CONFIG_M528x)
-/*
- *     Cache is totally broken on early 5282 silicon. So far now we
- *     disable its cache all together.
- */
 .macro CACHE_ENABLE
-       movel   #0x01000000,%d0
-       movec   %d0,%CACR               /* invalidate cache */
        nop
-       movel   #0x0000c000,%d0         /* set SDRAM cached only */
-       movec   %d0,%ACR0
-       movel   #0x00000000,%d0         /* no other regions cached */
-       movec   %d0,%ACR1
-       movel   #0x00000000,%d0         /* configure cache */
-       movec   %d0,%CACR               /* enable cache */
+       movel   #0x01000000, %d0
+       movec   %d0, %CACR              /* Invalidate cache */
+       nop
+       movel   #0x0000c020, %d0        /* Set SDRAM cached only */
+       movec   %d0, %ACR0
+       movel   #0xff00c000, %d0        /* Cache Flash also */
+       movec   %d0, %ACR1
+       movel   #0x80000200, %d0        /* Setup cache mask */
+       movec   %d0, %CACR              /* Enable cache */
        nop
 .endm
 #endif /* CONFIG_M528x */
index 350c6090b5c1ed5f3959ad5eae8d4b06b7bc283c..b93f8ba8a248e6269a0d8385217dc6f50893cb3a 100644 (file)
@@ -21,7 +21,7 @@
 #define        MCFDMA_BASE1            0x240           /* Base address of DMA 1 */
 #elif defined(CONFIG_M5272)
 #define        MCFDMA_BASE0            0x0e0           /* Base address of DMA 0 */
-#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
 /* These are relative to the IPSBAR, not MBAR */
 #define        MCFDMA_BASE0            0x100           /* Base address of DMA 0 */
 #define        MCFDMA_BASE1            0x140           /* Base address of DMA 1 */
index ac8823df255461a30d9a8b91538a5b9704a70b05..11daf5ceb7b4e6daebeb8a25690386521f397353 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef _ASM_ASMMACRO_32_H
 #define _ASM_ASMMACRO_32_H
 
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
index bbed35511f5a79d61b22437de45d6a1c96a86ca4..559c355b9b868e007461fea60c17d4c4d6ac36f2 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef _ASM_ASMMACRO_64_H
 #define _ASM_ASMMACRO_64_H
 
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
index b90b11d0b886b34ea45a57c012c57d77fe54daf3..3f2470e9e67808d63f2bdbb71418ebcb36d2c212 100644 (file)
@@ -49,7 +49,4 @@ do {                                                                  \
 
 extern void arch_init_irq(void);
 
-struct irqaction;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif /* _ASM_IRQ_H */
index 3ccfe09fa744c0bdc702ac0c9a8e7cbc4d0d9856..9c2af1b00e19732f07f1cebd1ec6ec0a2a9de331 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <linux/config.h>
 
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 
 #define __str2(x) #x
 #define __str(x) __str2(x)
index 114d3eb98a6aa39fc4ad01a46c4ab6aa6c3650ab..4d0135b111567e5e59956a3bd30bf7b58f86debe 100644 (file)
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  */
 
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
-
-#define spin_lock_init(x)      do { (x)->lock = 0; } while(0)
-
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define spin_unlock_wait(x)    do { barrier(); } while ((x)->lock)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x)        ((x)->lock != 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+               do { cpu_relax(); } while ((x)->lock)
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
@@ -38,13 +28,13 @@ typedef struct {
  * We make no fairness assumptions.  They have a cost.
  */
 
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
        unsigned int tmp;
 
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_spin_lock        \n"
+               "       .set    noreorder       # __raw_spin_lock       \n"
                "1:     ll      %1, %2                                  \n"
                "       bnez    %1, 1b                                  \n"
                "        li     %1, 1                                   \n"
@@ -58,7 +48,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
                : "memory");
        } else {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_spin_lock        \n"
+               "       .set    noreorder       # __raw_spin_lock       \n"
                "1:     ll      %1, %2                                  \n"
                "       bnez    %1, 1b                                  \n"
                "        li     %1, 1                                   \n"
@@ -72,10 +62,10 @@ static inline void _raw_spin_lock(spinlock_t *lock)
        }
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        __asm__ __volatile__(
-       "       .set    noreorder       # _raw_spin_unlock      \n"
+       "       .set    noreorder       # __raw_spin_unlock     \n"
        "       sync                                            \n"
        "       sw      $0, %0                                  \n"
        "       .set\treorder                                   \n"
@@ -84,13 +74,13 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
        : "memory");
 }
 
-static inline unsigned int _raw_spin_trylock(spinlock_t *lock)
+static inline unsigned int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        unsigned int temp, res;
 
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_spin_trylock     \n"
+               "       .set    noreorder       # __raw_spin_trylock    \n"
                "1:     ll      %0, %3                                  \n"
                "       ori     %2, %0, 1                               \n"
                "       sc      %2, %1                                  \n"
@@ -104,7 +94,7 @@ static inline unsigned int _raw_spin_trylock(spinlock_t *lock)
                : "memory");
        } else {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_spin_trylock     \n"
+               "       .set    noreorder       # __raw_spin_trylock    \n"
                "1:     ll      %0, %3                                  \n"
                "       ori     %2, %0, 1                               \n"
                "       sc      %2, %1                                  \n"
@@ -129,24 +119,13 @@ static inline unsigned int _raw_spin_trylock(spinlock_t *lock)
  * read-locks.
  */
 
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-
-#define rwlock_init(x)  do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
        unsigned int tmp;
 
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_read_lock        \n"
+               "       .set    noreorder       # __raw_read_lock       \n"
                "1:     ll      %1, %2                                  \n"
                "       bltz    %1, 1b                                  \n"
                "        addu   %1, 1                                   \n"
@@ -160,7 +139,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
                : "memory");
        } else {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_read_lock        \n"
+               "       .set    noreorder       # __raw_read_lock       \n"
                "1:     ll      %1, %2                                  \n"
                "       bltz    %1, 1b                                  \n"
                "        addu   %1, 1                                   \n"
@@ -177,13 +156,13 @@ static inline void _raw_read_lock(rwlock_t *rw)
 /* Note the use of sub, not subu which will make the kernel die with an
    overflow exception if we ever try to unlock an rwlock that is already
    unlocked or is being held by a writer.  */
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
        unsigned int tmp;
 
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
-               "1:     ll      %1, %2          # _raw_read_unlock      \n"
+               "1:     ll      %1, %2          # __raw_read_unlock     \n"
                "       sub     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
                "       beqzl   %1, 1b                                  \n"
@@ -193,7 +172,7 @@ static inline void _raw_read_unlock(rwlock_t *rw)
                : "memory");
        } else {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_read_unlock      \n"
+               "       .set    noreorder       # __raw_read_unlock     \n"
                "1:     ll      %1, %2                                  \n"
                "       sub     %1, 1                                   \n"
                "       sc      %1, %0                                  \n"
@@ -206,13 +185,13 @@ static inline void _raw_read_unlock(rwlock_t *rw)
        }
 }
 
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
        unsigned int tmp;
 
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_write_lock       \n"
+               "       .set    noreorder       # __raw_write_lock      \n"
                "1:     ll      %1, %2                                  \n"
                "       bnez    %1, 1b                                  \n"
                "        lui    %1, 0x8000                              \n"
@@ -226,7 +205,7 @@ static inline void _raw_write_lock(rwlock_t *rw)
                : "memory");
        } else {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_write_lock       \n"
+               "       .set    noreorder       # __raw_write_lock      \n"
                "1:     ll      %1, %2                                  \n"
                "       bnez    %1, 1b                                  \n"
                "        lui    %1, 0x8000                              \n"
@@ -241,26 +220,26 @@ static inline void _raw_write_lock(rwlock_t *rw)
        }
 }
 
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
        __asm__ __volatile__(
-       "       sync                    # _raw_write_unlock     \n"
+       "       sync                    # __raw_write_unlock    \n"
        "       sw      $0, %0                                  \n"
        : "=m" (rw->lock)
        : "m" (rw->lock)
        : "memory");
 }
 
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
 {
        unsigned int tmp;
        int ret;
 
        if (R10000_LLSC_WAR) {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_write_trylock    \n"
+               "       .set    noreorder       # __raw_write_trylock   \n"
                "       li      %2, 0                                   \n"
                "1:     ll      %1, %3                                  \n"
                "       bnez    %1, 2f                                  \n"
@@ -277,7 +256,7 @@ static inline int _raw_write_trylock(rwlock_t *rw)
                : "memory");
        } else {
                __asm__ __volatile__(
-               "       .set    noreorder       # _raw_write_trylock    \n"
+               "       .set    noreorder       # __raw_write_trylock   \n"
                "       li      %2, 0                                   \n"
                "1:     ll      %1, %3                                  \n"
                "       bnez    %1, 2f                                  \n"
diff --git a/include/asm-mips/spinlock_types.h b/include/asm-mips/spinlock_types.h
new file mode 100644 (file)
index 0000000..ce26c50
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _ASM_SPINLOCK_TYPES_H
+#define _ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index fb42f99f85278adffcf6c41aa5f94f1378e7750b..7b5e64600bc894e980180a33d710fa2e4e9d2fdc 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
-#include <asm/offset.h>
+#include <asm/asm-offsets.h>
 
                .macro  SAVE_AT
                .set    push
diff --git a/include/asm-mips/vr41xx/tb0287.h b/include/asm-mips/vr41xx/tb0287.h
new file mode 100644 (file)
index 0000000..dd98323
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  tb0287.h, Include file for TANBAC TB0287 mini-ITX board.
+ *
+ *  Copyright (C) 2005  Media Lab Inc. <ito@mlb.co.jp>
+ *
+ *  This code is largely based on tb0219.h.
+ *
+ *  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
+ */
+#ifndef __TANBAC_TB0287_H
+#define __TANBAC_TB0287_H
+
+#include <asm/vr41xx/vr41xx.h>
+
+/*
+ * General-Purpose I/O Pin Number
+ */
+#define TB0287_PCI_SLOT_PIN            2
+#define TB0287_SM501_PIN               3
+#define TB0287_SIL680A_PIN             8
+#define TB0287_RTL8110_PIN             13
+
+/*
+ * Interrupt Number
+ */
+#define TB0287_PCI_SLOT_IRQ            GIU_IRQ(TB0287_PCI_SLOT_PIN)
+#define TB0287_SM501_IRQ               GIU_IRQ(TB0287_SM501_PIN)
+#define TB0287_SIL680A_IRQ             GIU_IRQ(TB0287_SIL680A_PIN)
+#define TB0287_RTL8110_IRQ             GIU_IRQ(TB0287_RTL8110_PIN)
+
+#endif /* __TANBAC_TB0287_H */
index cbc286f49b365e059b560a78fed96e622da0df19..30b023411fefdbea9b62715ff32835265ce51856 100644 (file)
@@ -63,7 +63,7 @@
        .level 2.0w
 #endif
 
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/page.h>
 
 #include <asm/asmregs.h>
index e24f7579adb0d70dd4024f81883d2a4ada961c9a..048a2c7fd0c0a54530fdabb5350915652fa1e2c0 100644 (file)
 #  define ATOMIC_HASH_SIZE 4
 #  define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))
 
-extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
+extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
 
-/* Can't use _raw_spin_lock_irq because of #include problems, so
+/* Can't use raw_spin_lock_irq because of #include problems, so
  * this is the substitute */
 #define _atomic_spin_lock_irqsave(l,f) do {    \
-       spinlock_t *s = ATOMIC_HASH(l);         \
+       raw_spinlock_t *s = ATOMIC_HASH(l);             \
        local_irq_save(f);                      \
-       _raw_spin_lock(s);                      \
+       __raw_spin_lock(s);                     \
 } while(0)
 
 #define _atomic_spin_unlock_irqrestore(l,f) do {       \
-       spinlock_t *s = ATOMIC_HASH(l);                 \
-       _raw_spin_unlock(s);                            \
+       raw_spinlock_t *s = ATOMIC_HASH(l);                     \
+       __raw_spin_unlock(s);                           \
        local_irq_restore(f);                           \
 } while(0)
 
index 928e5ef850bd2a3fb8cbc2fec71305069ec57db9..af7db694b22d3b9a0827828cd3a15128f9233b35 100644 (file)
@@ -2,7 +2,7 @@
 #define _PARISC_BITOPS_H
 
 #include <linux/compiler.h>
-#include <asm/system.h>
+#include <asm/spinlock.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 
index 06732719d927f7d2a5d71151d9245ccda79bccba..aa592d8c0e396247f759df4a382511819a70750b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <asm/cache.h> /* for flush_user_dcache_range_asm() proto */
 
 /* The usual comment is "Caches aren't brain-dead on the <architecture>".
  * Unfortunately, that doesn't apply to PA-RISC. */
index 0b61f51d84670a7c37dfd916950e9c831389a782..a9dfadd05658e7a548c73318385c73b791999593 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <linux/spinlock_types.h>
 
 #include <asm/hardware.h>
 #include <asm/page.h>
index 679ea1c651efed3f0fa9f35639c5a56c6b899194..43eaa6e742e06f3a1f77dffca9d6eccf61fa29d4 100644 (file)
@@ -2,30 +2,25 @@
 #define __ASM_SPINLOCK_H
 
 #include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/spinlock_types.h>
 
 /* Note that PA-RISC has to use `1' to mean unlocked and `0' to mean locked
  * since it only has load-and-zero. Moreover, at least on some PA processors,
  * the semaphore address has to be 16-byte aligned.
  */
 
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-#define __SPIN_LOCK_UNLOCKED   { { 1, 1, 1, 1 } }
-#undef SPIN_LOCK_UNLOCKED
-#define SPIN_LOCK_UNLOCKED (spinlock_t) __SPIN_LOCK_UNLOCKED
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-static inline int spin_is_locked(spinlock_t *x)
+static inline int __raw_spin_is_locked(raw_spinlock_t *x)
 {
        volatile unsigned int *a = __ldcw_align(x);
        return *a == 0;
 }
 
-#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+               do { cpu_relax(); } while (__raw_spin_is_locked(x))
 
-static inline void _raw_spin_lock(spinlock_t *x)
+static inline void __raw_spin_lock(raw_spinlock_t *x)
 {
        volatile unsigned int *a;
 
@@ -36,7 +31,7 @@ static inline void _raw_spin_lock(spinlock_t *x)
        mb();
 }
 
-static inline void _raw_spin_unlock(spinlock_t *x)
+static inline void __raw_spin_unlock(raw_spinlock_t *x)
 {
        volatile unsigned int *a;
        mb();
@@ -45,7 +40,7 @@ static inline void _raw_spin_unlock(spinlock_t *x)
        mb();
 }
 
-static inline int _raw_spin_trylock(spinlock_t *x)
+static inline int __raw_spin_trylock(raw_spinlock_t *x)
 {
        volatile unsigned int *a;
        int ret;
@@ -57,131 +52,38 @@ static inline int _raw_spin_trylock(spinlock_t *x)
 
        return ret;
 }
-       
-#define spin_lock_own(LOCK, LOCATION)  ((void)0)
-
-#else /* !(CONFIG_DEBUG_SPINLOCK) */
-
-#define SPINLOCK_MAGIC 0x1D244B3C
-
-#define __SPIN_LOCK_UNLOCKED   { { 1, 1, 1, 1 }, SPINLOCK_MAGIC, 10, __FILE__ , NULL, 0, -1, NULL, NULL }
-#undef SPIN_LOCK_UNLOCKED
-#define SPIN_LOCK_UNLOCKED (spinlock_t) __SPIN_LOCK_UNLOCKED
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-#define CHECK_LOCK(x)                                                  \
-       do {                                                            \
-               if (unlikely((x)->magic != SPINLOCK_MAGIC)) {                   \
-                       printk(KERN_ERR "%s:%d: spin_is_locked"         \
-                       " on uninitialized spinlock %p.\n",             \
-                               __FILE__, __LINE__, (x));               \
-               }                                                       \
-       } while(0)
-
-#define spin_is_locked(x)                                              \
-       ({                                                              \
-               CHECK_LOCK(x);                                          \
-               volatile unsigned int *a = __ldcw_align(x);             \
-               if (unlikely((*a == 0) && (x)->babble)) {                               \
-                       (x)->babble--;                                  \
-                       printk("KERN_WARNING                            \
-                               %s:%d: spin_is_locked(%s/%p) already"   \
-                               " locked by %s:%d in %s at %p(%d)\n",   \
-                               __FILE__,__LINE__, (x)->module, (x),    \
-                               (x)->bfile, (x)->bline, (x)->task->comm,\
-                               (x)->previous, (x)->oncpu);             \
-               }                                                       \
-               *a == 0;                                                \
-       })
-
-#define spin_unlock_wait(x)                                            \
-       do {                                                            \
-               CHECK_LOCK(x);                                          \
-               volatile unsigned int *a = __ldcw_align(x);             \
-               if (unlikely((*a == 0) && (x)->babble)) {                               \
-                       (x)->babble--;                                  \
-                       printk("KERN_WARNING                            \
-                               %s:%d: spin_unlock_wait(%s/%p)"         \
-                               " owned by %s:%d in %s at %p(%d)\n",    \
-                               __FILE__,__LINE__, (x)->module, (x),    \
-                               (x)->bfile, (x)->bline, (x)->task->comm,\
-                               (x)->previous, (x)->oncpu);             \
-               }                                                       \
-               barrier();                                              \
-       } while (*((volatile unsigned char *)(__ldcw_align(x))) == 0)
-
-extern void _dbg_spin_lock(spinlock_t *lock, const char *base_file, int line_no);
-extern void _dbg_spin_unlock(spinlock_t *lock, const char *, int);
-extern int _dbg_spin_trylock(spinlock_t * lock, const char *, int);
-
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-
-#define _raw_spin_unlock(lock) _dbg_spin_unlock(lock, __FILE__, __LINE__)
-#define _raw_spin_lock(lock) _dbg_spin_lock(lock, __FILE__, __LINE__)
-#define _raw_spin_trylock(lock) _dbg_spin_trylock(lock, __FILE__, __LINE__)
-
-/* just in case we need it */
-#define spin_lock_own(LOCK, LOCATION)                                  \
-do {                                                                   \
-       volatile unsigned int *a = __ldcw_align(LOCK);                  \
-       if (!((*a == 0) && ((LOCK)->oncpu == smp_processor_id())))      \
-               printk("KERN_WARNING                                    \
-                       %s: called on %d from %p but lock %s on %d\n",  \
-                       LOCATION, smp_processor_id(),                   \
-                       __builtin_return_address(0),                    \
-                       (*a == 0) ? "taken" : "freed", (LOCK)->on_cpu); \
-} while (0)
-
-#endif /* !(CONFIG_DEBUG_SPINLOCK) */
 
 /*
  * Read-write spinlocks, allowing multiple readers
  * but only one writer.
  */
-typedef struct {
-       spinlock_t lock;
-       volatile int counter;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { __SPIN_LOCK_UNLOCKED, 0 }
-
-#define rwlock_init(lp)        do { *(lp) = RW_LOCK_UNLOCKED; } while (0)
 
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
 /* read_lock, read_unlock are pretty straightforward.  Of course it somehow
  * sucks we end up saving/restoring flags twice for read_lock_irqsave aso. */
 
-#ifdef CONFIG_DEBUG_RWLOCK
-extern void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline);
-#define _raw_read_lock(rw) _dbg_read_lock(rw, __FILE__, __LINE__)
-#else
-static  __inline__ void _raw_read_lock(rwlock_t *rw)
+static  __inline__ void __raw_read_lock(raw_rwlock_t *rw)
 {
        unsigned long flags;
        local_irq_save(flags);
-       _raw_spin_lock(&rw->lock); 
+       __raw_spin_lock(&rw->lock);
 
        rw->counter++;
 
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
        local_irq_restore(flags);
 }
-#endif /* CONFIG_DEBUG_RWLOCK */
 
-static  __inline__ void _raw_read_unlock(rwlock_t *rw)
+static  __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
 {
        unsigned long flags;
        local_irq_save(flags);
-       _raw_spin_lock(&rw->lock); 
+       __raw_spin_lock(&rw->lock);
 
        rw->counter--;
 
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
        local_irq_restore(flags);
 }
 
@@ -194,20 +96,17 @@ static  __inline__ void _raw_read_unlock(rwlock_t *rw)
  * writers) in interrupt handlers someone fucked up and we'd dead-lock
  * sooner or later anyway.   prumpf */
 
-#ifdef CONFIG_DEBUG_RWLOCK
-extern void _dbg_write_lock(rwlock_t * rw, const char *bfile, int bline);
-#define _raw_write_lock(rw) _dbg_write_lock(rw, __FILE__, __LINE__)
-#else
-static  __inline__ void _raw_write_lock(rwlock_t *rw)
+static  __inline__ void __raw_write_lock(raw_rwlock_t *rw)
 {
 retry:
-       _raw_spin_lock(&rw->lock);
+       __raw_spin_lock(&rw->lock);
 
        if(rw->counter != 0) {
                /* this basically never happens */
-               _raw_spin_unlock(&rw->lock);
+               __raw_spin_unlock(&rw->lock);
 
-               while(rw->counter != 0);
+               while (rw->counter != 0)
+                       cpu_relax();
 
                goto retry;
        }
@@ -215,26 +114,21 @@ retry:
        /* got it.  now leave without unlocking */
        rw->counter = -1; /* remember we are locked */
 }
-#endif /* CONFIG_DEBUG_RWLOCK */
 
 /* write_unlock is absolutely trivial - we don't have to wait for anything */
 
-static  __inline__ void _raw_write_unlock(rwlock_t *rw)
+static  __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
 {
        rw->counter = 0;
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
 }
 
-#ifdef CONFIG_DEBUG_RWLOCK
-extern int _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
-#define _raw_write_trylock(rw) _dbg_write_trylock(rw, __FILE__, __LINE__)
-#else
-static  __inline__ int _raw_write_trylock(rwlock_t *rw)
+static  __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
 {
-       _raw_spin_lock(&rw->lock);
+       __raw_spin_lock(&rw->lock);
        if (rw->counter != 0) {
                /* this basically never happens */
-               _raw_spin_unlock(&rw->lock);
+               __raw_spin_unlock(&rw->lock);
 
                return 0;
        }
@@ -243,14 +137,13 @@ static  __inline__ int _raw_write_trylock(rwlock_t *rw)
        rw->counter = -1; /* remember we are locked */
        return 1;
 }
-#endif /* CONFIG_DEBUG_RWLOCK */
 
-static __inline__ int is_read_locked(rwlock_t *rw)
+static __inline__ int __raw_is_read_locked(raw_rwlock_t *rw)
 {
        return rw->counter > 0;
 }
 
-static __inline__ int is_write_locked(rwlock_t *rw)
+static __inline__ int __raw_is_write_locked(raw_rwlock_t *rw)
 {
        return rw->counter < 0;
 }
diff --git a/include/asm-parisc/spinlock_types.h b/include/asm-parisc/spinlock_types.h
new file mode 100644 (file)
index 0000000..785bba8
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int lock[4];
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { { 1, 1, 1, 1 } }
+
+typedef struct {
+       raw_spinlock_t lock;
+       volatile int counter;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { __RAW_SPIN_LOCK_UNLOCKED, 0 }
+
+#endif
index 81c543339036cb1f31df3b41863b3e7c9157fa3e..26ff844a21c18a36eed14cccdb951e68d8411187 100644 (file)
@@ -160,29 +160,7 @@ static inline void set_eiem(unsigned long val)
 })
 
 #ifdef CONFIG_SMP
-/*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
-       volatile unsigned int lock[4];
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned long magic;
-       volatile unsigned int babble;
-       const char *module;
-       char *bfile;
-       int bline;
-       int oncpu;
-       void *previous;
-       struct task_struct * task;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
-
+# define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
 #endif
 
 #define KERNEL_START (0x10100000 - 0x1000)
index 538ea8ef509b99f4d2ec3350d64e12bd27450332..12f1bce037be7f57c422b26246b692838b4fbc9d 100644 (file)
 
 #include <asm-generic/siginfo.h>
 
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRANCH    (__SI_FAULT|3)  /* process taken branch trap */
+#define TRAP_HWBKPT    (__SI_FAULT|4)  /* hardware breakpoint or watchpoint */
+#undef NSIGTRAP
+#define NSIGTRAP       4
+
 #endif /* _ASM_POWERPC_SIGINFO_H */
index b4b270457eddce51eac0e30a6e604fb82630740e..55752474d0d9471ec28da282b5ed9024dd699f5c 100644 (file)
@@ -404,9 +404,5 @@ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
 extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
 extern atomic_t ppc_n_lost_interrupts;
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif /* _ASM_IRQ_H */
 #endif /* __KERNEL__ */
index 9d4e4ea530c3a7c2c5dd34b0d01d6824914a08f3..7043c164b5375d98a9ae8794b1b77db89653b3ab 100644 (file)
@@ -142,4 +142,11 @@ do {                                                                             \
 #define PTRACE_GETEVRREGS      20
 #define PTRACE_SETEVRREGS      21
 
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG    25
+#define PTRACE_SET_DEBUGREG    26
+
 #endif
index 88b4222154d48517cb8ba5e7014a69d306929ccb..73c33e3ef9c6d635a03a439a6b038490d0bd2a3e 100644 (file)
 #define PVR_STB03XXX   0x40310000
 #define PVR_NP405H     0x41410000
 #define PVR_NP405L     0x41610000
-#define PVR_440GP_RB   0x40120440
-#define PVR_440GP_RC1  0x40120481
-#define PVR_440GP_RC2  0x40200481
-#define PVR_440GX_RA   0x51b21850
-#define PVR_440GX_RB   0x51b21851
-#define PVR_440GX_RC   0x51b21892
 #define PVR_601                0x00010000
 #define PVR_602                0x00050000
 #define PVR_603                0x00030000
index 17530c232c7690c6a47a0b87a0e50ea4e23b8788..829481c0a9dc2fd6321a71a629045d3a5d94f4b1 100644 (file)
@@ -41,6 +41,10 @@ extern void smp_send_xmon_break(int cpu);
 struct pt_regs;
 extern void smp_message_recv(int, struct pt_regs *);
 
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
+extern void cpu_die(void) __attribute__((noreturn));
+
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 #define PROC_CHANGE_PENALTY    20
 
@@ -64,6 +68,8 @@ extern struct klock_info_struct klock_info;
 
 #else /* !(CONFIG_SMP) */
 
+static inline void cpu_die(void) { }
+
 #endif /* !(CONFIG_SMP) */
 
 #endif /* !(_PPC_SMP_H) */
index 909199aae1047f2baf6934e384bd0918eb3f855e..20edcf2a6e0ce47eddfb7b213f62e06304c5a093 100644 (file)
@@ -5,41 +5,21 @@
 
 /*
  * Simple spin lock operations.
+ *
+ * (the type definitions are in asm/raw_spinlock_types.h)
  */
 
-typedef struct {
-       volatile unsigned long lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       volatile unsigned long owner_pc;
-       volatile unsigned long owner_cpu;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#ifdef __KERNEL__
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_DEBUG_INIT     , 0, 0
-#else
-#define SPINLOCK_DEBUG_INIT     /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0 SPINLOCK_DEBUG_INIT }
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-static inline void _raw_spin_lock(spinlock_t *lock)
+#define __raw_spin_is_locked(x)                ((x)->lock != 0)
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
        unsigned long tmp;
 
        __asm__ __volatile__(
-       "b      1f              # spin_lock\n\
+       "b      1f              # __raw_spin_lock\n\
 2:     lwzx    %0,0,%1\n\
        cmpwi   0,%0,0\n\
        bne+    2b\n\
@@ -55,21 +35,13 @@ static inline void _raw_spin_lock(spinlock_t *lock)
        : "cr0", "memory");
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-       __asm__ __volatile__("eieio             # spin_unlock": : :"memory");
+       __asm__ __volatile__("eieio     # __raw_spin_unlock": : :"memory");
        lock->lock = 0;
 }
 
-#define _raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock))
-
-#else
-
-extern void _raw_spin_lock(spinlock_t *lock);
-extern void _raw_spin_unlock(spinlock_t *lock);
-extern int _raw_spin_trylock(spinlock_t *lock);
-
-#endif
+#define __raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock))
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -81,22 +53,11 @@ extern int _raw_spin_trylock(spinlock_t *lock);
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef struct {
-       volatile signed int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
 
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
+#define __raw_read_can_lock(rw)        ((rw)->lock >= 0)
+#define __raw_write_can_lock(rw)       (!(rw)->lock)
 
-#define read_can_lock(rw)      ((rw)->lock >= 0)
-#define write_can_lock(rw)     (!(rw)->lock)
-
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-static __inline__ int _raw_read_trylock(rwlock_t *rw)
+static __inline__ int __raw_read_trylock(raw_rwlock_t *rw)
 {
        signed int tmp;
 
@@ -116,7 +77,7 @@ static __inline__ int _raw_read_trylock(rwlock_t *rw)
        return tmp > 0;
 }
 
-static __inline__ void _raw_read_lock(rwlock_t *rw)
+static __inline__ void __raw_read_lock(raw_rwlock_t *rw)
 {
        signed int tmp;
 
@@ -137,7 +98,7 @@ static __inline__ void _raw_read_lock(rwlock_t *rw)
        : "cr0", "memory");
 }
 
-static __inline__ void _raw_read_unlock(rwlock_t *rw)
+static __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
 {
        signed int tmp;
 
@@ -153,7 +114,7 @@ static __inline__ void _raw_read_unlock(rwlock_t *rw)
        : "cr0", "memory");
 }
 
-static __inline__ int _raw_write_trylock(rwlock_t *rw)
+static __inline__ int __raw_write_trylock(raw_rwlock_t *rw)
 {
        signed int tmp;
 
@@ -173,7 +134,7 @@ static __inline__ int _raw_write_trylock(rwlock_t *rw)
        return tmp == 0;
 }
 
-static __inline__ void _raw_write_lock(rwlock_t *rw)
+static __inline__ void __raw_write_lock(raw_rwlock_t *rw)
 {
        signed int tmp;
 
@@ -194,22 +155,10 @@ static __inline__ void _raw_write_lock(rwlock_t *rw)
        : "cr0", "memory");
 }
 
-static __inline__ void _raw_write_unlock(rwlock_t *rw)
+static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
 {
        __asm__ __volatile__("eieio             # write_unlock": : :"memory");
        rw->lock = 0;
 }
 
-#else
-
-extern void _raw_read_lock(rwlock_t *rw);
-extern void _raw_read_unlock(rwlock_t *rw);
-extern void _raw_write_lock(rwlock_t *rw);
-extern void _raw_write_unlock(rwlock_t *rw);
-extern int _raw_read_trylock(rwlock_t *rw);
-extern int _raw_write_trylock(rwlock_t *rw);
-
-#endif
-
 #endif /* __ASM_SPINLOCK_H */
-#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/spinlock_types.h b/include/asm-ppc/spinlock_types.h
new file mode 100644 (file)
index 0000000..7919ccc
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned long lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile signed int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index 513a334c581032ec21ddc33819d7e25dad5b4bd0..d754ab570fe0eba855c55e53446564076f6d895f 100644 (file)
@@ -88,6 +88,7 @@ extern void *cacheable_memcpy(void *, const void *, unsigned int);
 extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
 extern void bad_page_fault(struct pt_regs *, unsigned long, int);
 extern void die(const char *, struct pt_regs *, long);
+extern void _exception(int, struct pt_regs *, int, unsigned long);
 #ifdef CONFIG_BOOKE_WDT
 extern u32 booke_wdt_enabled;
 extern u32 booke_wdt_period;
index 4f668a4baff01b13427e59be038280075c7e835c..ab7c3cf24888cd6c6fb2f3663cd835f95d088f7b 100644 (file)
 #define H_PP1                  (1UL<<(63-62))
 #define H_PP2                  (1UL<<(63-63))
 
+/* DABRX flags */
+#define H_DABRX_HYPERVISOR     (1UL<<(63-61))
+#define H_DABRX_KERNEL         (1UL<<(63-62))
+#define H_DABRX_USER           (1UL<<(63-63))
+
 /* pSeries hypervisor opcodes */
 #define H_REMOVE               0x04
 #define H_ENTER                        0x08
 #define H_VIO_SIGNAL           0x104
 #define H_SEND_CRQ             0x108
 #define H_COPY_RDMA             0x110
+#define H_SET_XDABR            0x134
 #define H_STUFF_TCE            0x138
 #define H_PUT_TCE_INDIRECT     0x13C
 #define H_VTERM_PARTNER_INFO   0x150
index 9a1ef4427ed2dfa0b2923f99ef2f8c4098cf4011..8027160ec96d005966b3afd54edac45fecfa5512 100644 (file)
@@ -88,6 +88,7 @@ struct machdep_calls {
 
        /* PCI stuff */
        void            (*pcibios_fixup)(void);
+       int             (*pci_probe_mode)(struct pci_bus *);
 
        void            (*restart)(char *cmd);
        void            (*power_off)(void);
@@ -173,10 +174,6 @@ extern sys_ctrler_t sys_ctrler;
 void ppc64_boot_msg(unsigned int src, const char *msg);
 /* Print a termination message (print only -- does not stop the kernel) */
 void ppc64_terminate_msg(unsigned int src, const char *msg);
-/* Print something that needs attention (device error, etc) */
-void ppc64_attention_msg(unsigned int src, const char *msg);
-/* Print a dump progress message. */
-void ppc64_dump_msg(unsigned int src, const char *msg);
 
 static inline void log_error(char *buf, unsigned int err_type, int fatal)
 {
index 6b4a5b1f695e916cf72b38f29ec44f8ed1e132ec..d8991389ab3960c598fbd030c7dc6e0385f40b90 100644 (file)
@@ -119,5 +119,10 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
        return PCI_DN(busdn)->phb;
 }
 
+/* Return values for ppc_md.pci_probe_mode function */
+#define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
+#define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */
+#define PCI_PROBE_DEVTREE      1       /* Instantiate from device tree */
+
 #endif
 #endif /* __KERNEL__ */
index f4a5fb7d67c7ccd24a0aa82c06672e8f54461565..72dd2449ee76224f6f9f1748e5ef69c81b4843bd 100644 (file)
@@ -107,5 +107,14 @@ static inline long plpar_put_term_char(unsigned long termno,
                                  lbuf[1]);
 }
 
+static inline long plpar_set_xdabr(unsigned long address, unsigned long flags)
+{
+       return plpar_hcall_norets(H_SET_XDABR, address, flags);
+}
+
+static inline long plpar_set_dabr(unsigned long val)
+{
+       return plpar_hcall_norets(H_SET_DABR, val);
+}
 
 #endif /* _PPC64_PLPAR_WRAPPERS_H */
index 8bd7aa959385d01d33c530526609e7302cf97921..4146189006e32cac1d8d11d618e8f02498bfe1ce 100644 (file)
@@ -433,6 +433,7 @@ struct thread_struct {
        unsigned long   start_tb;       /* Start purr when proc switched in */
        unsigned long   accum_tb;       /* Total accumilated purr for process */
        unsigned long   vdso_base;      /* base of the vDSO library */
+       unsigned long   dabr;           /* Data address breakpoint register */
 #ifdef CONFIG_ALTIVEC
        /* Complete AltiVec register set */
        vector128       vr[32] __attribute((aligned(16)));
index af03547f9c7edf4151afbbb3f29d5bbd89fddba6..b1babb7296733632baeaa2ea60a21e0399bc60e0 100644 (file)
 
 #ifndef _PPC64_PTRACE_COMMON_H
 #define _PPC64_PTRACE_COMMON_H
+
+#include <linux/config.h>
+#include <asm/system.h>
+
 /*
  * Set of msr bits that gdb can change on behalf of a process.
  */
@@ -69,4 +73,92 @@ static inline void clear_single_step(struct task_struct *task)
        clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
 }
 
+#ifdef CONFIG_ALTIVEC
+/*
+ * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go.
+ * The transfer totals 34 quadword.  Quadwords 0-31 contain the
+ * corresponding vector registers.  Quadword 32 contains the vscr as the
+ * last word (offset 12) within that quadword.  Quadword 33 contains the
+ * vrsave as the first word (offset 0) within the quadword.
+ *
+ * This definition of the VMX state is compatible with the current PPC32
+ * ptrace interface.  This allows signal handling and ptrace to use the
+ * same structures.  This also simplifies the implementation of a bi-arch
+ * (combined (32- and 64-bit) gdb.
+ */
+
+/*
+ * Get contents of AltiVec register state in task TASK
+ */
+static inline int get_vrregs(unsigned long __user *data,
+                            struct task_struct *task)
+{
+       unsigned long regsize;
+
+       /* copy AltiVec registers VR[0] .. VR[31] */
+       regsize = 32 * sizeof(vector128);
+       if (copy_to_user(data, task->thread.vr, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VSCR */
+       regsize = 1 * sizeof(vector128);
+       if (copy_to_user(data, &task->thread.vscr, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VRSAVE */
+       if (put_user(task->thread.vrsave, (u32 __user *)data))
+               return -EFAULT;
+
+       return 0;
+}
+
+/*
+ * Write contents of AltiVec register state into task TASK.
+ */
+static inline int set_vrregs(struct task_struct *task,
+                            unsigned long __user *data)
+{
+       unsigned long regsize;
+
+       /* copy AltiVec registers VR[0] .. VR[31] */
+       regsize = 32 * sizeof(vector128);
+       if (copy_from_user(task->thread.vr, data, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VSCR */
+       regsize = 1 * sizeof(vector128);
+       if (copy_from_user(&task->thread.vscr, data, regsize))
+               return -EFAULT;
+       data += (regsize / sizeof(unsigned long));
+
+       /* copy VRSAVE */
+       if (get_user(task->thread.vrsave, (u32 __user *)data))
+               return -EFAULT;
+
+       return 0;
+}
+#endif
+
+static inline int ptrace_set_debugreg(struct task_struct *task,
+                                     unsigned long addr, unsigned long data)
+{
+       /* We only support one DABR and no IABRS at the moment */
+       if (addr > 0)
+               return -EINVAL;
+
+       /* The bottom 3 bits are flags */
+       if ((data & ~0x7UL) >= TASK_SIZE)
+               return -EIO;
+
+       /* Ensure translation is on */
+       if (data && !(data & DABR_TRANSLATION))
+               return -EIO;
+
+       task->thread.dabr = data;
+       return 0;
+}
+
 #endif /* _PPC64_PTRACE_COMMON_H */
index c96aad28fc081fc721d8c66fbca460864f1ea7b5..3a55377f1fd30fe2781c7cd817f2ca283f832265 100644 (file)
  */
 
 #ifndef __ASSEMBLY__
-#define PPC_REG unsigned long
+
 struct pt_regs {
-       PPC_REG gpr[32];
-       PPC_REG nip;
-       PPC_REG msr;
-       PPC_REG orig_gpr3;      /* Used for restarting system calls */
-       PPC_REG ctr;
-       PPC_REG link;
-       PPC_REG xer;
-       PPC_REG ccr;
-       PPC_REG softe;          /* Soft enabled/disabled */
-       PPC_REG trap;           /* Reason for being here */
-       PPC_REG dar;            /* Fault registers */
-       PPC_REG dsisr;
-       PPC_REG result;         /* Result of a system call */
+       unsigned long gpr[32];
+       unsigned long nip;
+       unsigned long msr;
+       unsigned long orig_gpr3; /* Used for restarting system calls */
+       unsigned long ctr;
+       unsigned long link;
+       unsigned long xer;
+       unsigned long ccr;
+       unsigned long softe;    /* Soft enabled/disabled */
+       unsigned long trap;     /* Reason for being here */
+       unsigned long dar;      /* Fault registers */
+       unsigned long dsisr;
+       unsigned long result;   /* Result of a system call */
 };
 
-#define PPC_REG_32 unsigned int
 struct pt_regs32 {
-       PPC_REG_32 gpr[32];
-       PPC_REG_32 nip;
-       PPC_REG_32 msr;
-       PPC_REG_32 orig_gpr3;   /* Used for restarting system calls */
-       PPC_REG_32 ctr;
-       PPC_REG_32 link;
-       PPC_REG_32 xer;
-       PPC_REG_32 ccr;
-       PPC_REG_32 mq;          /* 601 only (not used at present) */
-                               /* Used on APUS to hold IPL value. */
-       PPC_REG_32 trap;                /* Reason for being here */
-       PPC_REG_32 dar;         /* Fault registers */
-       PPC_REG_32 dsisr;
-       PPC_REG_32 result;      /* Result of a system call */
+       unsigned int gpr[32];
+       unsigned int nip;
+       unsigned int msr;
+       unsigned int orig_gpr3; /* Used for restarting system calls */
+       unsigned int ctr;
+       unsigned int link;
+       unsigned int xer;
+       unsigned int ccr;
+       unsigned int mq;        /* 601 only (not used at present) */
+       unsigned int trap;      /* Reason for being here */
+       unsigned int dar;       /* Fault registers */
+       unsigned int dsisr;
+       unsigned int result;    /* Result of a system call */
 };
 
+#ifdef __KERNEL__
+
 #define instruction_pointer(regs) ((regs)->nip)
+
 #ifdef CONFIG_SMP
 extern unsigned long profile_pc(struct pt_regs *regs);
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
 
-#endif /* __ASSEMBLY__ */
-
-#define STACK_FRAME_OVERHEAD   112     /* size of minimum stack frame */
-
-/* Size of dummy stack frame allocated when calling signal handler. */
-#define __SIGNAL_FRAMESIZE     128
-#define __SIGNAL_FRAMESIZE32   64
-
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
 #define force_successful_syscall_return()   \
@@ -89,6 +82,16 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define TRAP(regs)             ((regs)->trap & ~0xF)
 #define CHECK_FULL_REGS(regs)  BUG_ON(regs->trap & 1)
 
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#define STACK_FRAME_OVERHEAD   112     /* size of minimum stack frame */
+
+/* Size of dummy stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE     128
+#define __SIGNAL_FRAMESIZE32   64
+
 /*
  * Offsets used by 'ptrace' system call interface.
  */
@@ -135,17 +138,21 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define PT_XER 37
 #define PT_CCR 38
 #define PT_SOFTE 39
+#define PT_TRAP        40
+#define PT_DAR 41
+#define PT_DSISR 42
 #define PT_RESULT 43
 
 #define PT_FPR0        48
 
-/* Kernel and userspace will both use this PT_FPSCR value.  32-bit apps will have
- * visibility to the asm-ppc/ptrace.h header instead of this one.
+/*
+ * Kernel and userspace will both use this PT_FPSCR value.  32-bit apps will
+ * have visibility to the asm-ppc/ptrace.h header instead of this one.
  */
-#define PT_FPSCR (PT_FPR0 + 32)          /* each FP reg occupies 1 slot in 64-bit space */
+#define PT_FPSCR (PT_FPR0 + 32)        /* each FP reg occupies 1 slot in 64-bit space */
 
 #ifdef __KERNEL__
-#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)          /* each FP reg occupies 2 32-bit userspace slots */
+#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1)        /* each FP reg occupies 2 32-bit userspace slots */
 #endif
 
 #define PT_VR0 82      /* each Vector reg occupies 2 slots in 64-bit */
@@ -173,17 +180,34 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 #define PTRACE_GETVRREGS       18
 #define PTRACE_SETVRREGS       19
 
-/* Additional PTRACE requests implemented on PowerPC. */
-#define PPC_PTRACE_GETREGS           0x99  /* Get GPRs 0 - 31 */
-#define PPC_PTRACE_SETREGS           0x98  /* Set GPRs 0 - 31 */
-#define PPC_PTRACE_GETFPREGS       0x97  /* Get FPRs 0 - 31 */
-#define PPC_PTRACE_SETFPREGS       0x96  /* Set FPRs 0 - 31 */
-#define PPC_PTRACE_PEEKTEXT_3264  0x95  /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKDATA_3264  0x94  /* Read word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKETEXT_3264  0x93  /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEDATA_3264  0x92  /* Write word at location ADDR on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_PEEKUSR_3264   0x91  /* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */
-#define PPC_PTRACE_POKEUSR_3264   0x90  /* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */
+/*
+ * While we dont have 64bit book E processors, we need to reserve the
+ * relevant ptrace calls for 32bit compatibility.
+ */
+#if 0
+#define PTRACE_GETEVRREGS       20
+#define PTRACE_SETEVRREGS       21
+#endif
 
+/*
+ * Get or set a debug register. The first 16 are DABR registers and the
+ * second 16 are IABR registers.
+ */
+#define PTRACE_GET_DEBUGREG    25
+#define PTRACE_SET_DEBUGREG    26
+
+/* Additional PTRACE requests implemented on PowerPC. */
+#define PPC_PTRACE_GETREGS     0x99    /* Get GPRs 0 - 31 */
+#define PPC_PTRACE_SETREGS     0x98    /* Set GPRs 0 - 31 */
+#define PPC_PTRACE_GETFPREGS   0x97    /* Get FPRs 0 - 31 */
+#define PPC_PTRACE_SETFPREGS   0x96    /* Set FPRs 0 - 31 */
+
+/* Calls to trace a 64bit program from a 32bit program */
+#define PPC_PTRACE_PEEKTEXT_3264 0x95
+#define PPC_PTRACE_PEEKDATA_3264 0x94
+#define PPC_PTRACE_POKETEXT_3264 0x93
+#define PPC_PTRACE_POKEDATA_3264 0x92
+#define PPC_PTRACE_PEEKUSR_3264  0x91
+#define PPC_PTRACE_POKEUSR_3264  0x90
 
 #endif /* _PPC64_PTRACE_H */
index acd11564dd752d64a8e29951e3beb55eee0f09c4..14cb895bb607245477e4dc466e7dd6a227491956 100644 (file)
  * 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.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
  */
 #include <linux/config.h>
 #include <asm/paca.h>
 #include <asm/hvcall.h>
 #include <asm/iSeries/HvCall.h>
 
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
+#define __raw_spin_is_locked(x)                ((x)->slock != 0)
 
-typedef struct {
-       volatile signed int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
+/*
+ * This returns the old value in the lock, so we succeeded
+ * in getting the lock if the return value is 0.
+ */
+static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock)
+{
+       unsigned long tmp, tmp2;
 
-#ifdef __KERNEL__
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0 }
+       __asm__ __volatile__(
+"      lwz             %1,%3(13)               # __spin_trylock\n\
+1:     lwarx           %0,0,%2\n\
+       cmpwi           0,%0,0\n\
+       bne-            2f\n\
+       stwcx.          %1,0,%2\n\
+       bne-            1b\n\
+       isync\n\
+2:"    : "=&r" (tmp), "=&r" (tmp2)
+       : "r" (&lock->slock), "i" (offsetof(struct paca_struct, lock_token))
+       : "cr0", "memory");
 
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+       return tmp;
+}
 
-static __inline__ void _raw_spin_unlock(spinlock_t *lock)
+static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock)
 {
-       __asm__ __volatile__("lwsync    # spin_unlock": : :"memory");
-       lock->lock = 0;
+       return __spin_trylock(lock) == 0;
 }
 
 /*
@@ -64,44 +70,15 @@ static __inline__ void _raw_spin_unlock(spinlock_t *lock)
 #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 /* We only yield to the hypervisor if we are in shared processor mode */
 #define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc)
-extern void __spin_yield(spinlock_t *lock);
-extern void __rw_yield(rwlock_t *lock);
+extern void __spin_yield(raw_spinlock_t *lock);
+extern void __rw_yield(raw_rwlock_t *lock);
 #else /* SPLPAR || ISERIES */
 #define __spin_yield(x)        barrier()
 #define __rw_yield(x)  barrier()
 #define SHARED_PROCESSOR       0
 #endif
-extern void spin_unlock_wait(spinlock_t *lock);
-
-/*
- * This returns the old value in the lock, so we succeeded
- * in getting the lock if the return value is 0.
- */
-static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
-{
-       unsigned long tmp, tmp2;
-
-       __asm__ __volatile__(
-"      lwz             %1,%3(13)               # __spin_trylock\n\
-1:     lwarx           %0,0,%2\n\
-       cmpwi           0,%0,0\n\
-       bne-            2f\n\
-       stwcx.          %1,0,%2\n\
-       bne-            1b\n\
-       isync\n\
-2:"    : "=&r" (tmp), "=&r" (tmp2)
-       : "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
-       : "cr0", "memory");
-
-       return tmp;
-}
-
-static int __inline__ _raw_spin_trylock(spinlock_t *lock)
-{
-       return __spin_trylock(lock) == 0;
-}
 
-static void __inline__ _raw_spin_lock(spinlock_t *lock)
+static void __inline__ __raw_spin_lock(raw_spinlock_t *lock)
 {
        while (1) {
                if (likely(__spin_trylock(lock) == 0))
@@ -110,12 +87,12 @@ static void __inline__ _raw_spin_lock(spinlock_t *lock)
                        HMT_low();
                        if (SHARED_PROCESSOR)
                                __spin_yield(lock);
-               } while (unlikely(lock->lock != 0));
+               } while (unlikely(lock->slock != 0));
                HMT_medium();
        }
 }
 
-static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
 {
        unsigned long flags_dis;
 
@@ -128,12 +105,20 @@ static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flag
                        HMT_low();
                        if (SHARED_PROCESSOR)
                                __spin_yield(lock);
-               } while (unlikely(lock->lock != 0));
+               } while (unlikely(lock->slock != 0));
                HMT_medium();
                local_irq_restore(flags_dis);
        }
 }
 
+static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+       __asm__ __volatile__("lwsync    # __raw_spin_unlock": : :"memory");
+       lock->slock = 0;
+}
+
+extern void __raw_spin_unlock_wait(raw_spinlock_t *lock);
+
 /*
  * Read-write spinlocks, allowing multiple readers
  * but only one writer.
@@ -144,24 +129,15 @@ static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flag
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 
-#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-#define read_can_lock(rw)      ((rw)->lock >= 0)
-#define write_can_lock(rw)     (!(rw)->lock)
-
-static __inline__ void _raw_write_unlock(rwlock_t *rw)
-{
-       __asm__ __volatile__("lwsync            # write_unlock": : :"memory");
-       rw->lock = 0;
-}
+#define __raw_read_can_lock(rw)                ((rw)->lock >= 0)
+#define __raw_write_can_lock(rw)       (!(rw)->lock)
 
 /*
  * This returns the old value in the lock + 1,
  * so we got a read lock if the return value is > 0.
  */
-static long __inline__ __read_trylock(rwlock_t *rw)
+static long __inline__ __read_trylock(raw_rwlock_t *rw)
 {
        long tmp;
 
@@ -180,45 +156,11 @@ static long __inline__ __read_trylock(rwlock_t *rw)
        return tmp;
 }
 
-static int __inline__ _raw_read_trylock(rwlock_t *rw)
-{
-       return __read_trylock(rw) > 0;
-}
-
-static void __inline__ _raw_read_lock(rwlock_t *rw)
-{
-       while (1) {
-               if (likely(__read_trylock(rw) > 0))
-                       break;
-               do {
-                       HMT_low();
-                       if (SHARED_PROCESSOR)
-                               __rw_yield(rw);
-               } while (unlikely(rw->lock < 0));
-               HMT_medium();
-       }
-}
-
-static void __inline__ _raw_read_unlock(rwlock_t *rw)
-{
-       long tmp;
-
-       __asm__ __volatile__(
-       "eieio                          # read_unlock\n\
-1:     lwarx           %0,0,%1\n\
-       addic           %0,%0,-1\n\
-       stwcx.          %0,0,%1\n\
-       bne-            1b"
-       : "=&r"(tmp)
-       : "r"(&rw->lock)
-       : "cr0", "memory");
-}
-
 /*
  * This returns the old value in the lock,
  * so we got the write lock if the return value is 0.
  */
-static __inline__ long __write_trylock(rwlock_t *rw)
+static __inline__ long __write_trylock(raw_rwlock_t *rw)
 {
        long tmp, tmp2;
 
@@ -237,12 +179,21 @@ static __inline__ long __write_trylock(rwlock_t *rw)
        return tmp;
 }
 
-static int __inline__ _raw_write_trylock(rwlock_t *rw)
+static void __inline__ __raw_read_lock(raw_rwlock_t *rw)
 {
-       return __write_trylock(rw) == 0;
+       while (1) {
+               if (likely(__read_trylock(rw) > 0))
+                       break;
+               do {
+                       HMT_low();
+                       if (SHARED_PROCESSOR)
+                               __rw_yield(rw);
+               } while (unlikely(rw->lock < 0));
+               HMT_medium();
+       }
 }
 
-static void __inline__ _raw_write_lock(rwlock_t *rw)
+static void __inline__ __raw_write_lock(raw_rwlock_t *rw)
 {
        while (1) {
                if (likely(__write_trylock(rw) == 0))
@@ -256,5 +207,35 @@ static void __inline__ _raw_write_lock(rwlock_t *rw)
        }
 }
 
-#endif /* __KERNEL__ */
+static int __inline__ __raw_read_trylock(raw_rwlock_t *rw)
+{
+       return __read_trylock(rw) > 0;
+}
+
+static int __inline__ __raw_write_trylock(raw_rwlock_t *rw)
+{
+       return __write_trylock(rw) == 0;
+}
+
+static void __inline__ __raw_read_unlock(raw_rwlock_t *rw)
+{
+       long tmp;
+
+       __asm__ __volatile__(
+       "eieio                          # read_unlock\n\
+1:     lwarx           %0,0,%1\n\
+       addic           %0,%0,-1\n\
+       stwcx.          %0,0,%1\n\
+       bne-            1b"
+       : "=&r"(tmp)
+       : "r"(&rw->lock)
+       : "cr0", "memory");
+}
+
+static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
+{
+       __asm__ __volatile__("lwsync    # write_unlock": : :"memory");
+       rw->lock = 0;
+}
+
 #endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-ppc64/spinlock_types.h b/include/asm-ppc64/spinlock_types.h
new file mode 100644 (file)
index 0000000..a37c8ea
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile signed int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index c0396428cc3c0c908bb723c111adff2a1d44ebac..375015c62f2071083b0114040404719fccc58818 100644 (file)
@@ -101,6 +101,9 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
+extern int set_dabr(unsigned long dabr);
+extern void _exception(int signr, struct pt_regs *regs, int code,
+                      unsigned long addr);
 extern int fix_alignment(struct pt_regs *regs);
 extern void bad_page_fault(struct pt_regs *regs, unsigned long address,
                           int sig);
index 321b23bba1ecf16987b724e45f79319f55972159..273dbecf8acef0465060133bbac01bab72118fc5 100644 (file)
@@ -27,25 +27,19 @@ _raw_compare_and_swap(volatile unsigned int *lock,
  * on the local processor, one does not.
  *
  * We make no fairness assumptions. They have a cost.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
  */
 
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} __attribute__ ((aligned (4))) spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0 }
-#define spin_lock_init(lp)     do { (lp)->lock = 0; } while(0)
-#define spin_unlock_wait(lp)   do { barrier(); } while(((volatile spinlock_t *)(lp))->lock)
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) ((x)->lock != 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
 
-extern void _raw_spin_lock_wait(spinlock_t *lp, unsigned int pc);
-extern int _raw_spin_trylock_retry(spinlock_t *lp, unsigned int pc);
+extern void _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc);
+extern int _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc);
 
-static inline void _raw_spin_lock(spinlock_t *lp)
+static inline void __raw_spin_lock(raw_spinlock_t *lp)
 {
        unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
 
@@ -53,7 +47,7 @@ static inline void _raw_spin_lock(spinlock_t *lp)
                _raw_spin_lock_wait(lp, pc);
 }
 
-static inline int _raw_spin_trylock(spinlock_t *lp)
+static inline int __raw_spin_trylock(raw_spinlock_t *lp)
 {
        unsigned long pc = 1 | (unsigned long) __builtin_return_address(0);
 
@@ -62,7 +56,7 @@ static inline int _raw_spin_trylock(spinlock_t *lp)
        return _raw_spin_trylock_retry(lp, pc);
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lp)
+static inline void __raw_spin_unlock(raw_spinlock_t *lp)
 {
        _raw_compare_and_swap(&lp->lock, lp->lock, 0);
 }
@@ -77,36 +71,25 @@ static inline void _raw_spin_unlock(spinlock_t *lp)
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef struct {
-       volatile unsigned int lock;
-       volatile unsigned long owner_pc;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
 
 /**
  * read_can_lock - would read_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define read_can_lock(x) ((int)(x)->lock >= 0)
+#define __raw_read_can_lock(x) ((int)(x)->lock >= 0)
 
 /**
  * write_can_lock - would write_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define write_can_lock(x) ((x)->lock == 0)
+#define __raw_write_can_lock(x) ((x)->lock == 0)
 
-extern void _raw_read_lock_wait(rwlock_t *lp);
-extern int _raw_read_trylock_retry(rwlock_t *lp);
-extern void _raw_write_lock_wait(rwlock_t *lp);
-extern int _raw_write_trylock_retry(rwlock_t *lp);
+extern void _raw_read_lock_wait(raw_rwlock_t *lp);
+extern int _raw_read_trylock_retry(raw_rwlock_t *lp);
+extern void _raw_write_lock_wait(raw_rwlock_t *lp);
+extern int _raw_write_trylock_retry(raw_rwlock_t *lp);
 
-static inline void _raw_read_lock(rwlock_t *rw)
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
        unsigned int old;
        old = rw->lock & 0x7fffffffU;
@@ -114,7 +97,7 @@ static inline void _raw_read_lock(rwlock_t *rw)
                _raw_read_lock_wait(rw);
 }
 
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
        unsigned int old, cmp;
 
@@ -125,18 +108,18 @@ static inline void _raw_read_unlock(rwlock_t *rw)
        } while (cmp != old);
 }
 
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
        if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0))
                _raw_write_lock_wait(rw);
 }
 
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
        _raw_compare_and_swap(&rw->lock, 0x80000000, 0);
 }
 
-static inline int _raw_read_trylock(rwlock_t *rw)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
 {
        unsigned int old;
        old = rw->lock & 0x7fffffffU;
@@ -145,7 +128,7 @@ static inline int _raw_read_trylock(rwlock_t *rw)
        return _raw_read_trylock_retry(rw);
 }
 
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
 {
        if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0))
                return 1;
diff --git a/include/asm-s390/spinlock_types.h b/include/asm-s390/spinlock_types.h
new file mode 100644 (file)
index 0000000..f79a221
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int lock;
+} __attribute__ ((aligned (4))) raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+       volatile unsigned int owner_pc;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0, 0 }
+
+#endif
index 831e52ee45b594a8a8583cfc32f806f9fa91acc9..614a8c13b72169cca810974d7388342887b4a03a 100644 (file)
@@ -587,10 +587,6 @@ static inline int generic_irq_demux(int irq)
 #define irq_canonicalize(irq)  (irq)
 #define irq_demux(irq)         __irq_demux(sh_mv.mv_irq_demux(irq))
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #if defined(CONFIG_CPU_SUBTYPE_SH73180)
 #include <asm/irq-sh73180.h>
 #endif
index e770b55649ebb88f0838e1b760844630f1cbf141..846322d4c35d489daf86e337518dbee79f5c738f 100644 (file)
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  */
-typedef struct {
-       volatile unsigned long lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
 
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0 }
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define spin_unlock_wait(x)    do { barrier(); } while (spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x)        ((x)->lock != 0)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+#define __raw_spin_unlock_wait(x) \
+       do { cpu_relax(); } while (__raw_spin_is_locked(x))
 
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
@@ -36,7 +27,7 @@ typedef struct {
  *
  * We make no fairness assumptions.  They have a cost.
  */
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
        __asm__ __volatile__ (
                "1:\n\t"
@@ -49,14 +40,14 @@ static inline void _raw_spin_lock(spinlock_t *lock)
        );
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        assert_spin_locked(lock);
 
        lock->lock = 0;
 }
 
-#define _raw_spin_trylock(x) (!test_and_set_bit(0, &(x)->lock))
+#define __raw_spin_trylock(x) (!test_and_set_bit(0, &(x)->lock))
 
 /*
  * Read-write spinlocks, allowing multiple readers but only one writer.
@@ -66,51 +57,40 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
  * needs to get a irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef struct {
-       spinlock_t lock;
-       atomic_t counter;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_BIAS           0x01000000
-#define RW_LOCK_UNLOCKED       (rwlock_t) { { 0 }, { RW_LOCK_BIAS } }
-#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while (0)
-
-static inline void _raw_read_lock(rwlock_t *rw)
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
-       _raw_spin_lock(&rw->lock);
+       __raw_spin_lock(&rw->lock);
 
        atomic_inc(&rw->counter);
 
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
 }
 
-static inline void _raw_read_unlock(rwlock_t *rw)
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
-       _raw_spin_lock(&rw->lock);
+       __raw_spin_lock(&rw->lock);
 
        atomic_dec(&rw->counter);
 
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
 }
 
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
-       _raw_spin_lock(&rw->lock);
+       __raw_spin_lock(&rw->lock);
        atomic_set(&rw->counter, -1);
 }
 
-static inline void _raw_write_unlock(rwlock_t *rw)
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
        atomic_set(&rw->counter, 0);
-       _raw_spin_unlock(&rw->lock);
+       __raw_spin_unlock(&rw->lock);
 }
 
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
-static inline int _raw_write_trylock(rwlock_t *rw)
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
 {
        if (atomic_sub_and_test(RW_LOCK_BIAS, &rw->counter))
                return 1;
@@ -121,4 +101,3 @@ static inline int _raw_write_trylock(rwlock_t *rw)
 }
 
 #endif /* __ASM_SH_SPINLOCK_H */
-
diff --git a/include/asm-sh/spinlock_types.h b/include/asm-sh/spinlock_types.h
new file mode 100644 (file)
index 0000000..8c41b6c
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __ASM_SH_SPINLOCK_TYPES_H
+#define __ASM_SH_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned long lock;
+} raw_spinlock_t;
+
+#define __SPIN_LOCK_UNLOCKED           { 0 }
+
+typedef struct {
+       raw_spinlock_t lock;
+       atomic_t counter;
+} raw_rwlock_t;
+
+#define RW_LOCK_BIAS                   0x01000000
+#define __RAW_RW_LOCK_UNLOCKED         { { 0 }, { RW_LOCK_BIAS } }
+
+#endif
index dd9d94d7e0ae46ba28fdd88db3c7a1041eb4e6be..a8ecb2d6977aadcb20bd40a652403a2f3f7fde07 100644 (file)
@@ -73,11 +73,11 @@ extern void show_regs(struct pt_regs *);
 #endif
 
 /*
- * The asm_offsets.h is a generated file, so we cannot include it.
+ * The asm-offsets.h is a generated file, so we cannot include it.
  * It may be OK for glibc headers, but it's utterly pointless for C code.
  * The assembly code using those offsets has to include it explicitly.
  */
-/* #include <asm/asm_offsets.h> */
+/* #include <asm/asm-offsets.h> */
 
 /* These are for pt_regs. */
 #define PT_PSR    0x0
index 0cbd87ad491280e620acbbfde7280d21ca1b367e..111727a2bb4e4f173b89434ddba3f4f00f191c91 100644 (file)
 
 #include <asm/psr.h>
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-struct _spinlock_debug {
-       unsigned char lock;
-       unsigned long owner_pc;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-};
-typedef struct _spinlock_debug spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0, 0 }
-#define spin_lock_init(lp)     do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(lp)  (*((volatile unsigned char *)(&((lp)->lock))) != 0)
-#define spin_unlock_wait(lp)   do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
-
-extern void _do_spin_lock(spinlock_t *lock, char *str);
-extern int _spin_trylock(spinlock_t *lock);
-extern void _do_spin_unlock(spinlock_t *lock);
-
-#define _raw_spin_trylock(lp)  _spin_trylock(lp)
-#define _raw_spin_lock(lock)   _do_spin_lock(lock, "spin_lock")
-#define _raw_spin_unlock(lock) _do_spin_unlock(lock)
-
-struct _rwlock_debug {
-       volatile unsigned int lock;
-       unsigned long owner_pc;
-       unsigned long reader_pc[NR_CPUS];
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-};
-typedef struct _rwlock_debug rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0, {0} }
-
-#define rwlock_init(lp)        do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
-
-extern void _do_read_lock(rwlock_t *rw, char *str);
-extern void _do_read_unlock(rwlock_t *rw, char *str);
-extern void _do_write_lock(rwlock_t *rw, char *str);
-extern void _do_write_unlock(rwlock_t *rw);
-
-#define _raw_read_lock(lock)   \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_read_lock(lock, "read_lock"); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_read_unlock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_read_unlock(lock, "read_unlock"); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_lock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_write_lock(lock, "write_lock"); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_unlock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_write_unlock(lock); \
-       local_irq_restore(flags); \
-} while(0)
-
-#else /* !CONFIG_DEBUG_SPINLOCK */
-
-typedef struct {
-       unsigned char lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) { 0 }
-
-#define spin_lock_init(lock)   (*((unsigned char *)(lock)) = 0)
-#define spin_is_locked(lock)    (*((volatile unsigned char *)(lock)) != 0)
+#define __raw_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
 
-#define spin_unlock_wait(lock) \
-do { \
-       barrier(); \
-} while(*((volatile unsigned char *)lock))
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
 
-extern __inline__ void _raw_spin_lock(spinlock_t *lock)
+extern __inline__ void __raw_spin_lock(raw_spinlock_t *lock)
 {
        __asm__ __volatile__(
        "\n1:\n\t"
@@ -121,7 +37,7 @@ extern __inline__ void _raw_spin_lock(spinlock_t *lock)
        : "g2", "memory", "cc");
 }
 
-extern __inline__ int _raw_spin_trylock(spinlock_t *lock)
+extern __inline__ int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        unsigned int result;
        __asm__ __volatile__("ldstub [%1], %0"
@@ -131,7 +47,7 @@ extern __inline__ int _raw_spin_trylock(spinlock_t *lock)
        return (result == 0);
 }
 
-extern __inline__ void _raw_spin_unlock(spinlock_t *lock)
+extern __inline__ void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        __asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
 }
@@ -147,23 +63,11 @@ extern __inline__ void _raw_spin_unlock(spinlock_t *lock)
  *
  * XXX This might create some problems with my dual spinlock
  * XXX scheme, deadlocks etc. -DaveM
- */
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
-
-#define rwlock_init(lp)        do { *(lp)= RW_LOCK_UNLOCKED; } while(0)
-
-
-/* Sort of like atomic_t's on Sparc, but even more clever.
+ *
+ * Sort of like atomic_t's on Sparc, but even more clever.
  *
  *     ------------------------------------
- *     | 24-bit counter           | wlock |  rwlock_t
+ *     | 24-bit counter           | wlock |  raw_rwlock_t
  *     ------------------------------------
  *      31                       8 7     0
  *
@@ -174,9 +78,9 @@ typedef struct {
  *
  * Unfortunately this scheme limits us to ~16,000,000 cpus.
  */
-extern __inline__ void _read_lock(rwlock_t *rw)
+extern __inline__ void __read_lock(raw_rwlock_t *rw)
 {
-       register rwlock_t *lp asm("g1");
+       register raw_rwlock_t *lp asm("g1");
        lp = rw;
        __asm__ __volatile__(
        "mov    %%o7, %%g4\n\t"
@@ -187,16 +91,16 @@ extern __inline__ void _read_lock(rwlock_t *rw)
        : "g2", "g4", "memory", "cc");
 }
 
-#define _raw_read_lock(lock) \
+#define __raw_read_lock(lock) \
 do {   unsigned long flags; \
        local_irq_save(flags); \
-       _read_lock(lock); \
+       __raw_read_lock(lock); \
        local_irq_restore(flags); \
 } while(0)
 
-extern __inline__ void _read_unlock(rwlock_t *rw)
+extern __inline__ void __read_unlock(raw_rwlock_t *rw)
 {
-       register rwlock_t *lp asm("g1");
+       register raw_rwlock_t *lp asm("g1");
        lp = rw;
        __asm__ __volatile__(
        "mov    %%o7, %%g4\n\t"
@@ -207,16 +111,16 @@ extern __inline__ void _read_unlock(rwlock_t *rw)
        : "g2", "g4", "memory", "cc");
 }
 
-#define _raw_read_unlock(lock) \
+#define __raw_read_unlock(lock) \
 do {   unsigned long flags; \
        local_irq_save(flags); \
-       _read_unlock(lock); \
+       __raw_read_unlock(lock); \
        local_irq_restore(flags); \
 } while(0)
 
-extern __inline__ void _raw_write_lock(rwlock_t *rw)
+extern __inline__ void __raw_write_lock(raw_rwlock_t *rw)
 {
-       register rwlock_t *lp asm("g1");
+       register raw_rwlock_t *lp asm("g1");
        lp = rw;
        __asm__ __volatile__(
        "mov    %%o7, %%g4\n\t"
@@ -227,11 +131,9 @@ extern __inline__ void _raw_write_lock(rwlock_t *rw)
        : "g2", "g4", "memory", "cc");
 }
 
-#define _raw_write_unlock(rw)  do { (rw)->lock = 0; } while(0)
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
+#define __raw_write_unlock(rw) do { (rw)->lock = 0; } while(0)
 
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 
 #endif /* !(__ASSEMBLY__) */
 
diff --git a/include/asm-sparc/spinlock_types.h b/include/asm-sparc/spinlock_types.h
new file mode 100644 (file)
index 0000000..0a0fb11
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __SPARC_SPINLOCK_TYPES_H
+#define __SPARC_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       unsigned char lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index a02c4370eb42e0d1c8f6043a25f900e0ea03ff2c..ec85d12d73b98a353e0fdcaf346489b09f80839a 100644 (file)
  * must be pre-V9 branches.
  */
 
-#ifndef CONFIG_DEBUG_SPINLOCK
+#define __raw_spin_is_locked(lp)       ((lp)->lock != 0)
 
-typedef struct {
-       volatile unsigned char lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED     (spinlock_t) {0,}
+#define __raw_spin_unlock_wait(lp)     \
+       do {    rmb();                  \
+       } while((lp)->lock)
 
-#define spin_lock_init(lp)     do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(lp)  ((lp)->lock != 0)
-
-#define spin_unlock_wait(lp)   \
-do {   rmb();                  \
-} while((lp)->lock)
-
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
        unsigned long tmp;
 
@@ -67,7 +56,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
        : "memory");
 }
 
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        unsigned long result;
 
@@ -81,7 +70,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
        return (result == 0UL);
 }
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        __asm__ __volatile__(
 "      membar          #StoreStore | #LoadStore\n"
@@ -91,7 +80,7 @@ static inline void _raw_spin_unlock(spinlock_t *lock)
        : "memory");
 }
 
-static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
 {
        unsigned long tmp1, tmp2;
 
@@ -115,51 +104,9 @@ static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
        : "memory");
 }
 
-#else /* !(CONFIG_DEBUG_SPINLOCK) */
-
-typedef struct {
-       volatile unsigned char lock;
-       unsigned int owner_pc, owner_cpu;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, 0xff }
-#define spin_lock_init(lp)     do { *(lp)= SPIN_LOCK_UNLOCKED; } while(0)
-#define spin_is_locked(__lock) ((__lock)->lock != 0)
-#define spin_unlock_wait(__lock)       \
-do { \
-       rmb(); \
-} while((__lock)->lock)
-
-extern void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller);
-extern void _do_spin_unlock(spinlock_t *lock);
-extern int _do_spin_trylock(spinlock_t *lock, unsigned long caller);
-
-#define _raw_spin_trylock(lp)  \
-       _do_spin_trylock(lp, (unsigned long) __builtin_return_address(0))
-#define _raw_spin_lock(lock)   \
-       _do_spin_lock(lock, "spin_lock", \
-                     (unsigned long) __builtin_return_address(0))
-#define _raw_spin_unlock(lock) _do_spin_unlock(lock)
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
 /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
 
-#ifndef CONFIG_DEBUG_SPINLOCK
-
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED       (rwlock_t) {0,}
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
-
-static void inline __read_lock(rwlock_t *lock)
+static void inline __read_lock(raw_rwlock_t *lock)
 {
        unsigned long tmp1, tmp2;
 
@@ -184,7 +131,7 @@ static void inline __read_lock(rwlock_t *lock)
        : "memory");
 }
 
-static void inline __read_unlock(rwlock_t *lock)
+static void inline __read_unlock(raw_rwlock_t *lock)
 {
        unsigned long tmp1, tmp2;
 
@@ -201,7 +148,7 @@ static void inline __read_unlock(rwlock_t *lock)
        : "memory");
 }
 
-static void inline __write_lock(rwlock_t *lock)
+static void inline __write_lock(raw_rwlock_t *lock)
 {
        unsigned long mask, tmp1, tmp2;
 
@@ -228,7 +175,7 @@ static void inline __write_lock(rwlock_t *lock)
        : "memory");
 }
 
-static void inline __write_unlock(rwlock_t *lock)
+static void inline __write_unlock(raw_rwlock_t *lock)
 {
        __asm__ __volatile__(
 "      membar          #LoadStore | #StoreStore\n"
@@ -238,7 +185,7 @@ static void inline __write_unlock(rwlock_t *lock)
        : "memory");
 }
 
-static int inline __write_trylock(rwlock_t *lock)
+static int inline __write_trylock(raw_rwlock_t *lock)
 {
        unsigned long mask, tmp1, tmp2, result;
 
@@ -263,78 +210,15 @@ static int inline __write_trylock(rwlock_t *lock)
        return result;
 }
 
-#define _raw_read_lock(p)      __read_lock(p)
-#define _raw_read_unlock(p)    __read_unlock(p)
-#define _raw_write_lock(p)     __write_lock(p)
-#define _raw_write_unlock(p)   __write_unlock(p)
-#define _raw_write_trylock(p)  __write_trylock(p)
-
-#else /* !(CONFIG_DEBUG_SPINLOCK) */
-
-typedef struct {
-       volatile unsigned long lock;
-       unsigned int writer_pc, writer_cpu;
-       unsigned int reader_pc[NR_CPUS];
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED       (rwlock_t) { 0, 0, 0xff, { } }
-#define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
-
-extern void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller);
-extern void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller);
-extern void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller);
-extern void _do_write_unlock(rwlock_t *rw, unsigned long caller);
-extern int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller);
-
-#define _raw_read_lock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_read_lock(lock, "read_lock", \
-                     (unsigned long) __builtin_return_address(0)); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_read_unlock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_read_unlock(lock, "read_unlock", \
-                     (unsigned long) __builtin_return_address(0)); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_lock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_write_lock(lock, "write_lock", \
-                     (unsigned long) __builtin_return_address(0)); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_unlock(lock) \
-do {   unsigned long flags; \
-       local_irq_save(flags); \
-       _do_write_unlock(lock, \
-                     (unsigned long) __builtin_return_address(0)); \
-       local_irq_restore(flags); \
-} while(0)
-
-#define _raw_write_trylock(lock) \
-({     unsigned long flags; \
-       int val; \
-       local_irq_save(flags); \
-       val = _do_write_trylock(lock, "write_trylock", \
-                               (unsigned long) __builtin_return_address(0)); \
-       local_irq_restore(flags); \
-       val; \
-})
-
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
-#define read_can_lock(rw)      (!((rw)->lock & 0x80000000UL))
-#define write_can_lock(rw)     (!(rw)->lock)
+#define __raw_read_lock(p)     __read_lock(p)
+#define __raw_read_unlock(p)   __read_unlock(p)
+#define __raw_write_lock(p)    __write_lock(p)
+#define __raw_write_unlock(p)  __write_unlock(p)
+#define __raw_write_trylock(p) __write_trylock(p)
+
+#define __raw_read_trylock(lock)       generic__raw_read_trylock(lock)
+#define __raw_read_can_lock(rw)                (!((rw)->lock & 0x80000000UL))
+#define __raw_write_can_lock(rw)       (!(rw)->lock)
 
 #endif /* !(__ASSEMBLY__) */
 
diff --git a/include/asm-sparc64/spinlock_types.h b/include/asm-sparc64/spinlock_types.h
new file mode 100644 (file)
index 0000000..e128112
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __SPARC64_SPINLOCK_TYPES_H
+#define __SPARC64_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned char lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 0 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { 0 }
+
+#endif
index bd850a249183d21399465a5b4a612c1f4b56d715..2c192abe9aeb0d29ac9ce1946214bc697af7c170 100644 (file)
@@ -96,8 +96,7 @@ extern unsigned long uml_physmem;
 
 #define __va_space (8*1024*1024)
 
-extern unsigned long to_phys(void *virt);
-extern void *to_virt(unsigned long phys);
+#include "mem.h"
 
 /* Cast to unsigned long before casting to void * to avoid a warning from
  * mmap_kmem about cutting a long long down to a void *.  Not sure that
index b48e0966ecd7b8b936a4be2a3e8cf06d9645edec..ed06170e0eddd448b5ac5f1a2b99613d170ed3ea 100644 (file)
@@ -326,14 +326,22 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
-extern phys_t page_to_phys(struct page *page);
-
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
 
-extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
+#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
+#define __virt_to_page(virt) phys_to_page(__pa(virt))
+#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
+
+#define mk_pte(page, pgprot) \
+       ({ pte_t pte;                                   \
+                                                       \
+       pte_set_val(pte, page_to_phys(page), (pgprot)); \
+       if (pte_present(pte))                           \
+               pte_mknewprot(pte_mknewpage(pte));      \
+       pte;})
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
@@ -410,8 +418,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #endif
 #endif
 
-extern struct page *phys_to_page(const unsigned long phys);
-extern struct page *__virt_to_page(const unsigned long virt);
 #define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
 
 /*
diff --git a/include/asm-um/spinlock_types.h b/include/asm-um/spinlock_types.h
new file mode 100644 (file)
index 0000000..e5a9429
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_SPINLOCK_TYPES_H
+#define __UM_SPINLOCK_TYPES_H
+
+#include "asm/arch/spinlock_types.h"
+
+#endif
index 16ec82e16b21aa18e400e269f386b3d52b3d9ee0..6c5d5ca8383a2abf4e2bd437bdb4ea865a6ec1e5 100644 (file)
@@ -109,9 +109,10 @@ extern unsigned int nmi_watchdog;
 #define NMI_LOCAL_APIC 2
 #define NMI_INVALID    3
 
+extern int disable_timer_pin_1;
+
 #endif /* CONFIG_X86_LOCAL_APIC */
 
-#define esr_disable 0
 extern unsigned boot_cpu_id;
 
 #endif /* __ASM_APIC_H */
index 9388062c4f6e52fd409ef099395ca55be862c21d..fb1c99ac669fda16727616a5172aac3c44de2c51 100644 (file)
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
 #define MAX_IO_APICS 128
+#define MAX_LOCAL_APIC 256
 
 /*
  * All x86-64 systems are xAPIC compatible.
index eed785667289fa34b0e287ba7240db98ab9866d3..80ac1fe966ac13ec3be908b2ec94bfaccefb40cc 100644 (file)
@@ -9,10 +9,8 @@
  */
 struct bug_frame {
        unsigned char ud2[2];
-       unsigned char mov;
-       /* should use 32bit offset instead, but the assembler doesn't 
-          like it */
-       char *filename;
+       unsigned char push;
+       signed int filename;
        unsigned char ret;
        unsigned short line;
 } __attribute__((packed));
@@ -25,8 +23,8 @@ struct bug_frame {
    The magic numbers generate mov $64bitimm,%eax ; ret $offset. */
 #define BUG()                                                          \
        asm volatile(                                                   \
-       "ud2 ; .byte 0xa3 ; .quad %c1 ; .byte 0xc2 ; .short %c0" ::     \
-                    "i"(__LINE__), "i" (__stringify(__FILE__)))
+       "ud2 ; pushq $%c1 ; ret $%c0" ::                                \
+                    "i"(__LINE__), "i" (__FILE__))
 void out_of_line_bug(void);
 #else
 static inline void out_of_line_bug(void) { }
index 0bc12655fa5be49e1feada576d01ba3a297b881c..fc2c5a6c262a20356c1fc1dc5e475fa84d97189c 100644 (file)
        .if \skipr11
        .else
        movq (%rsp),%r11
+       CFI_RESTORE r11
        .endif
        .if \skipr8910
        .else
        movq 1*8(%rsp),%r10
+       CFI_RESTORE r10
        movq 2*8(%rsp),%r9
+       CFI_RESTORE r9
        movq 3*8(%rsp),%r8
+       CFI_RESTORE r8
        .endif
        .if \skiprax
        .else
        movq 4*8(%rsp),%rax
+       CFI_RESTORE rax
        .endif
        .if \skiprcx
        .else
        movq 5*8(%rsp),%rcx
+       CFI_RESTORE rcx
        .endif
        .if \skiprdx
        .else
        movq 6*8(%rsp),%rdx
+       CFI_RESTORE rdx
        .endif
        movq 7*8(%rsp),%rsi
+       CFI_RESTORE rsi
        movq 8*8(%rsp),%rdi
+       CFI_RESTORE rdi
        .if ARG_SKIP+\addskip > 0
        addq $ARG_SKIP+\addskip,%rsp
        CFI_ADJUST_CFA_OFFSET   -(ARG_SKIP+\addskip)
 
        .macro RESTORE_REST
        movq (%rsp),%r15
+       CFI_RESTORE r15
        movq 1*8(%rsp),%r14
+       CFI_RESTORE r14
        movq 2*8(%rsp),%r13
+       CFI_RESTORE r13
        movq 3*8(%rsp),%r12
+       CFI_RESTORE r12
        movq 4*8(%rsp),%rbp
+       CFI_RESTORE rbp
        movq 5*8(%rsp),%rbx
+       CFI_RESTORE rbx
        addq $REST_SKIP,%rsp
        CFI_ADJUST_CFA_OFFSET   -(REST_SKIP)
        .endm
        .macro icebp
        .byte 0xf1
        .endm
-
-#ifdef CONFIG_FRAME_POINTER
-#define ENTER enter
-#define LEAVE leave
-#else
-#define ENTER
-#define LEAVE
-#endif
index 7db560ee6f7030fbf1d33ae823b0282ebdc2877b..bc8adecee66d74abc53ce61e1632112e6e28b941 100644 (file)
@@ -17,7 +17,7 @@ static inline struct task_struct *get_current(void)
 #else
 
 #ifndef ASM_OFFSET_H
-#include <asm/offset.h> 
+#include <asm/asm-offsets.h> 
 #endif
 
 #define GET_CURRENT(reg) movq %gs:(pda_pcurrent),reg
index c89b58bebee24619f9ae2b5ad903b752f5e1ec12..594e610f4a1e7d66aff1a12aa3666e7af8e9dd0a 100644 (file)
@@ -191,7 +191,7 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 /*
  * load one particular LDT into the current CPU
  */
-extern inline void load_LDT_nolock (mm_context_t *pc, int cpu)
+static inline void load_LDT_nolock (mm_context_t *pc, int cpu)
 {
        int count = pc->size;
 
index a416dc31634a207fa4ff3330810ef20dce2829c9..e784fdc524f1ac7be2dce7930995cccab58dc0f6 100644 (file)
@@ -85,6 +85,11 @@ static inline void dma_sync_single_for_device(struct device *hwdev,
        flush_write_buffers();
 }
 
+#define dma_sync_single_range_for_cpu(dev, dma_handle, offset, size, dir)       \
+        dma_sync_single_for_cpu(dev, dma_handle, size, dir)
+#define dma_sync_single_range_for_device(dev, dma_handle, offset, size, dir)    \
+        dma_sync_single_for_device(dev, dma_handle, size, dir)
+
 static inline void dma_sync_sg_for_cpu(struct device *hwdev,
                                       struct scatterlist *sg,
                                       int nelems, int direction)
index afd4212e860bd4e93409c16d38f0184c47c292f4..582757fc03655423d12d96b7baf43d986e6fe031 100644 (file)
 #define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
 #define CFI_OFFSET .cfi_offset
 #define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_REGISTER .cfi_register
+#define CFI_RESTORE .cfi_restore
+#define CFI_REMEMBER_STATE .cfi_remember_state
+#define CFI_RESTORE_STATE .cfi_restore_state
 
 #else
 
 #define CFI_ADJUST_CFA_OFFSET  #
 #define CFI_OFFSET     #
 #define CFI_REL_OFFSET #
+#define CFI_REGISTER   #
+#define CFI_RESTORE    #
+#define CFI_REMEMBER_STATE     #
+#define CFI_RESTORE_STATE      #
 
 #endif
 
index cf8b16cbe8db65e40ce5a84e6e18c8decdcba931..a582cfcf2231a631564bac9aeda0a4422d8f0ca6 100644 (file)
@@ -76,7 +76,7 @@ extern void __this_fixmap_does_not_exist(void);
  * directly without translation, we catch the bug with a NULL-deference
  * kernel oops. Illegal ranges of incoming indices are caught too.
  */
-extern inline unsigned long fix_to_virt(const unsigned int idx)
+static inline unsigned long fix_to_virt(const unsigned int idx)
 {
        /*
         * this branch gets completely eliminated after inlining,
index 27c381fa1c9d0e15eb0ff5e60c901a24336bd714..8661b476fb404f74e14d4ed7342e92575c37c50d 100644 (file)
@@ -9,11 +9,12 @@
 
 #define __ARCH_IRQ_STAT 1
 
-/* Generate a lvalue for a pda member. Should fix softirq.c instead to use
-   special access macros. This would generate better code. */ 
-#define __IRQ_STAT(cpu,member) (read_pda(me)->member)
+#define local_softirq_pending() read_pda(__softirq_pending)
 
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#define __ARCH_SET_SOFTIRQ_PENDING 1
+
+#define set_softirq_pending(x) write_pda(__softirq_pending, (x))
+#define or_softirq_pending(x)  or_pda(__softirq_pending, (x))
 
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
index 2b5cb2865d21de2b835da29788c5b5456e5f2670..dc97668ea0f9d3bc76ffa960fdfc50e596745847 100644 (file)
@@ -26,6 +26,7 @@
 struct hw_interrupt_type;
 #endif
 
+#define NMI_VECTOR             0x02
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
@@ -50,14 +51,15 @@ struct hw_interrupt_type;
  */
 #define SPURIOUS_APIC_VECTOR   0xff
 #define ERROR_APIC_VECTOR      0xfe
-#define INVALIDATE_TLB_VECTOR  0xfd
-#define RESCHEDULE_VECTOR      0xfc
-#define TASK_MIGRATION_VECTOR  0xfb
-#define CALL_FUNCTION_VECTOR   0xfa
-#define KDB_VECTOR     0xf9
-
-#define THERMAL_APIC_VECTOR    0xf0
-
+#define RESCHEDULE_VECTOR      0xfd
+#define CALL_FUNCTION_VECTOR   0xfc
+#define KDB_VECTOR             0xfb    /* reserved for KDB */
+#define THERMAL_APIC_VECTOR    0xfa
+/* 0xf9 free */
+#define INVALIDATE_TLB_VECTOR_END      0xf8
+#define INVALIDATE_TLB_VECTOR_START    0xf0    /* f0-f8 used for TLB flush */
+
+#define NUM_INVALIDATE_TLB_VECTORS     8
 
 /*
  * Local APIC timer IRQ vector is on a different priority level,
index 37fc3f149a5a6a2cf54cf194303d3975d32e85b9..52ff269fe05473ff255d8ced8c87f80a274e57b9 100644 (file)
@@ -48,7 +48,7 @@
  * Talk about misusing macros..
  */
 #define __OUT1(s,x) \
-extern inline void out##s(unsigned x value, unsigned short port) {
+static inline void out##s(unsigned x value, unsigned short port) {
 
 #define __OUT2(s,s1,s2) \
 __asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
@@ -58,7 +58,7 @@ __OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
 __OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} \
 
 #define __IN1(s) \
-extern inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
 
 #define __IN2(s,s1,s2) \
 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
@@ -68,12 +68,12 @@ __IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
 __IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
 
 #define __INS(s) \
-extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
 { __asm__ __volatile__ ("rep ; ins" #s \
 : "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
 #define __OUTS(s) \
-extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
 { __asm__ __volatile__ ("rep ; outs" #s \
 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
@@ -110,12 +110,12 @@ __OUTS(l)
  * Change virtual addresses to physical addresses and vv.
  * These are pretty trivial
  */
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
 {
        return __pa(address);
 }
 
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
 {
        return __va(address);
 }
@@ -130,7 +130,7 @@ extern inline void * phys_to_virt(unsigned long address)
 
 extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
-extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
 {
        return __ioremap(offset, size, 0);
 }
index 5e166b9d3bdeb766cb406eaeea764ef9402fb47d..022e9d340ad759cbc763458ed5df2cc186f2eafe 100644 (file)
 
 static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
 {
-       unsigned int icr =  APIC_DM_FIXED | shortcut | vector | dest;
-       if (vector == KDB_VECTOR)
-               icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI;
+       unsigned int icr = shortcut | dest;
+
+       switch (vector) {
+       default:
+               icr |= APIC_DM_FIXED | vector;
+               break;
+       case NMI_VECTOR:
+               /*
+                * Setup KDB IPI to be delivered as an NMI
+                */
+       case KDB_VECTOR:
+               icr |= APIC_DM_NMI;
+               break;
+       }
        return icr;
 }
 
@@ -66,7 +77,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsign
        /*
         * Send the IPI. The write to APIC_ICR fires this off.
         */
-       apic_write_around(APIC_ICR, cfg);
+       apic_write(APIC_ICR, cfg);
 }
 
 
@@ -92,7 +103,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
                 * prepare target chip field
                 */
                cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
-               apic_write_around(APIC_ICR2, cfg);
+               apic_write(APIC_ICR2, cfg);
 
                /*
                 * program the ICR
@@ -102,7 +113,7 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
                /*
                 * Send the IPI. The write to APIC_ICR fires this off.
                 */
-               apic_write_around(APIC_ICR, cfg);
+               apic_write(APIC_ICR, cfg);
        }
        local_irq_restore(flags);
 }
index 4482657777bbdbe2a576c3d073ac39eab113dada..fb724ba37ae630d85e38d77714822f08c973a537 100644 (file)
@@ -48,10 +48,6 @@ static __inline__ int irq_canonicalize(int irq)
 #define ARCH_HAS_NMI_WATCHDOG          /* See include/linux/nmi.h */
 #endif
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #ifdef CONFIG_HOTPLUG_CPU
 #include <linux/cpumask.h>
 extern void fixup_irqs(cpumask_t map);
index b90341994d80f6e78d18f685cca99e15baea8e37..f604e84c53039e784e10605b3b3e428af9d91deb 100644 (file)
@@ -46,7 +46,7 @@ extern void die(const char *,struct pt_regs *,long);
 extern void __die(const char *,struct pt_regs *,long);
 extern void show_registers(struct pt_regs *regs);
 extern void dump_pagetable(unsigned long);
-extern void oops_begin(void);
-extern void oops_end(void);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
 
 #endif
index c954f15c1a755f850c60b7e0f0c05a17b1feb2b8..3e72c41727c53af2f7ea75666aab6da56be79a5f 100644 (file)
@@ -29,7 +29,7 @@ static __inline__ void local_dec(local_t *v)
                :"m" (v->counter));
 }
 
-static __inline__ void local_add(unsigned long i, local_t *v)
+static __inline__ void local_add(unsigned int i, local_t *v)
 {
        __asm__ __volatile__(
                "addl %1,%0"
@@ -37,7 +37,7 @@ static __inline__ void local_add(unsigned long i, local_t *v)
                :"ir" (i), "m" (v->counter));
 }
 
-static __inline__ void local_sub(unsigned long i, local_t *v)
+static __inline__ void local_sub(unsigned int i, local_t *v)
 {
        __asm__ __volatile__(
                "subl %1,%0"
index 768413751b34288c0eb6b1ae5b56f4c5eecb3d13..b40c661f111e32b58f2c07bdd081a89fa4aa4b40 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <asm/smp.h>
 
-#define NODEMAPSIZE 0xff
+#define NODEMAPSIZE 0xfff
 
 /* Simple perfect hash to map physical addresses to node numbers */
 extern int memnode_shift; 
@@ -54,7 +54,7 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
 
 #define pfn_valid(pfn) ((pfn) >= num_physpages ? 0 : \
                        ({ u8 nid__ = pfn_to_nid(pfn); \
-                          nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); }))
+                          nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) < node_end_pfn(nid__); }))
 #endif
 
 #define local_mapnr(kvaddr) \
index ba15279a79d02f826e2c8d79f58d14d50671bfdf..4d727f3f5550bb2eadba0a20829bbf96ff970050 100644 (file)
 #define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32) 
 
 /* wrmsr with exception handling */
-#define wrmsr_safe(msr,a,b) ({ int ret__;                                              \
-       asm volatile("2: wrmsr ; xorl %0,%0\n"                                          \
-                    "1:\n\t"                                                           \
-                    ".section .fixup,\"ax\"\n\t"                                       \
-                    "3:  movl %4,%0 ; jmp 1b\n\t"                                      \
-                    ".previous\n\t"                                                    \
-                    ".section __ex_table,\"a\"\n"                                      \
-                    "   .align 8\n\t"                                                  \
-                    "   .quad  2b,3b\n\t"                                              \
-                    ".previous"                                                        \
-                    : "=a" (ret__)                                                     \
-                    : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT));\
+#define wrmsr_safe(msr,a,b) ({ int ret__;                      \
+       asm volatile("2: wrmsr ; xorl %0,%0\n"                  \
+                    "1:\n\t"                                   \
+                    ".section .fixup,\"ax\"\n\t"               \
+                    "3:  movl %4,%0 ; jmp 1b\n\t"              \
+                    ".previous\n\t"                            \
+                    ".section __ex_table,\"a\"\n"              \
+                    "   .align 8\n\t"                          \
+                    "   .quad  2b,3b\n\t"                      \
+                    ".previous"                                \
+                    : "=a" (ret__)                             \
+                    : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \
        ret__; })
 
 #define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32))
 
+#define rdmsr_safe(msr,a,b) \
+       ({ int ret__;                                           \
+         asm volatile ("1:       rdmsr\n"                      \
+                      "2:\n"                                   \
+                      ".section .fixup,\"ax\"\n"               \
+                      "3:       movl %4,%0\n"                  \
+                      " jmp 2b\n"                              \
+                      ".previous\n"                            \
+                      ".section __ex_table,\"a\"\n"            \
+                      " .align 8\n"                            \
+                      " .quad 1b,3b\n"                         \
+                      ".previous":"=&bDS" (ret__), "=a"(a), "=d"(b)\
+                      :"c"(msr), "i"(-EIO), "0"(0));           \
+         ret__; })             
+
 #define rdtsc(low,high) \
      __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
 
@@ -64,7 +79,7 @@
                          : "=a" (low), "=d" (high) \
                          : "c" (counter))
 
-extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
+static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
                         unsigned int *ecx, unsigned int *edx)
 {
        __asm__("cpuid"
@@ -90,7 +105,7 @@ static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
 /*
  * CPUID functions returning a single datum
  */
-extern inline unsigned int cpuid_eax(unsigned int op)
+static inline unsigned int cpuid_eax(unsigned int op)
 {
        unsigned int eax;
 
@@ -100,7 +115,7 @@ extern inline unsigned int cpuid_eax(unsigned int op)
                : "bx", "cx", "dx");
        return eax;
 }
-extern inline unsigned int cpuid_ebx(unsigned int op)
+static inline unsigned int cpuid_ebx(unsigned int op)
 {
        unsigned int eax, ebx;
 
@@ -110,7 +125,7 @@ extern inline unsigned int cpuid_ebx(unsigned int op)
                : "cx", "dx" );
        return ebx;
 }
-extern inline unsigned int cpuid_ecx(unsigned int op)
+static inline unsigned int cpuid_ecx(unsigned int op)
 {
        unsigned int eax, ecx;
 
@@ -120,7 +135,7 @@ extern inline unsigned int cpuid_ecx(unsigned int op)
                : "bx", "dx" );
        return ecx;
 }
-extern inline unsigned int cpuid_edx(unsigned int op)
+static inline unsigned int cpuid_edx(unsigned int op)
 {
        unsigned int eax, edx;
 
index 5c363a1482e43ecada598942d124b87d64a0041a..bcf55c3f7f7f35e0f162c504c5f6030578a857f8 100644 (file)
@@ -9,6 +9,7 @@ struct node {
 };
 
 extern int compute_hash_shift(struct node *nodes, int numnodes);
+extern int pxm_to_node(int nid);
 
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
@@ -16,6 +17,8 @@ extern void numa_add_cpu(int cpu);
 extern void numa_init_array(void);
 extern int numa_off;
 
+extern unsigned char apicid_to_node[256];
+
 #define NUMA_NO_NODE 0xff
 
 #endif
index 135ffaa0393b4d8aa5559241d0f512fb61251742..e5ab4d231f2ce2d837dea8476e7a024f5436060a 100644 (file)
@@ -32,6 +32,8 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+extern unsigned long end_pfn;
+
 void clear_page(void *);
 void copy_page(void *, void *);
 
@@ -111,7 +113,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)       (mem_map + (pfn))
 #define page_to_pfn(page)      ((unsigned long)((page) - mem_map))
-#define pfn_valid(pfn)         ((pfn) < max_mapnr)
+#define pfn_valid(pfn)         ((pfn) < end_pfn)
 #endif
 
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
index eeb3088a1c9e3d2fbbff1140b94fad85c69777f9..5a82a6762c2183411c5af255c8c32f2140a0e8c0 100644 (file)
@@ -50,10 +50,10 @@ extern int iommu_setup(char *opt);
  * address space.  The networking and block device layers use
  * this boolean for bounce buffer decisions
  *
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
+ * On x86-64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an hard or soft IOMMU is available.
  */
-#define PCI_DMA_BUS_IS_PHYS    (no_iommu ? 1 : 0)
+#define PCI_DMA_BUS_IS_PHYS 0
 
 /*
  * x86-64 always supports DAC, but sometimes it is useful to force
index 36b766cfc4d5630992c14e374d3a550fab7a54eb..bbf89aa8a1afe67a7178b5ada67c3e7368e71484 100644 (file)
 struct x8664_pda {
        struct task_struct *pcurrent;   /* Current process */
        unsigned long data_offset;      /* Per cpu data offset from linker address */
-       struct x8664_pda *me;       /* Pointer to itself */  
        unsigned long kernelstack;  /* top of kernel stack for current */ 
        unsigned long oldrsp;       /* user rsp for system call */
-       unsigned long irqrsp;       /* Old rsp for interrupts. */ 
         int irqcount;              /* Irq nesting counter. Starts with -1 */   
        int cpunumber;              /* Logical CPU number */
        char *irqstackptr;      /* top of irqstack */
@@ -22,7 +20,7 @@ struct x8664_pda {
        struct mm_struct *active_mm;
        int mmu_state;     
        unsigned apic_timer_irqs;
-} ____cacheline_aligned;
+} ____cacheline_aligned_in_smp;
 
 
 #define IRQSTACK_ORDER 2
@@ -42,13 +40,14 @@ extern void __bad_pda_field(void);
 #define pda_offset(field) offsetof(struct x8664_pda, field)
 
 #define pda_to_op(op,field,val) do { \
+       typedef typeof_field(struct x8664_pda, field) T__; \
        switch (sizeof_field(struct x8664_pda, field)) {                \
 case 2: \
-asm volatile(op "w %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
 case 4: \
-asm volatile(op "l %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
 case 8: \
-asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); break; \
+asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
        default: __bad_pda_field();                                     \
        } \
        } while (0)
@@ -58,7 +57,7 @@ asm volatile(op "q %0,%%gs:%P1"::"r" (val),"i"(pda_offset(field)):"memory"); bre
  * Unfortunately removing them causes all hell to break lose currently.
  */
 #define pda_from_op(op,field) ({ \
-       typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \
+       typeof_field(struct x8664_pda, field) ret__; \
        switch (sizeof_field(struct x8664_pda, field)) {                \
 case 2: \
 asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
@@ -75,6 +74,7 @@ asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); b
 #define write_pda(field,val) pda_to_op("mov",field,val)
 #define add_pda(field,val) pda_to_op("add",field,val)
 #define sub_pda(field,val) pda_to_op("sub",field,val)
+#define or_pda(field,val) pda_to_op("or",field,val)
 
 #endif
 
index deadd146978b189c002b81feaa305cdd5da3b8da..08cad2482bcbc56e88ac82cbfb82b0f1ff3f97bb 100644 (file)
@@ -18,12 +18,12 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
        set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
 }
 
-extern __inline__ pmd_t *get_pmd(void)
+static inline pmd_t *get_pmd(void)
 {
        return (pmd_t *)get_zeroed_page(GFP_KERNEL);
 }
 
-extern __inline__ void pmd_free(pmd_t *pmd)
+static inline void pmd_free(pmd_t *pmd)
 {
        BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
        free_page((unsigned long)pmd);
@@ -86,13 +86,13 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
 /* Should really implement gc for free page table pages. This could be
    done with a reference count in struct page. */
 
-extern __inline__ void pte_free_kernel(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
 {
        BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
        free_page((unsigned long)pte); 
 }
 
-extern inline void pte_free(struct page *pte)
+static inline void pte_free(struct page *pte)
 {
        __free_page(pte);
 } 
index 5e0f2fdab0d35885f75f1177d54d18b4117808ec..1dc110ba82d63e80781f514b79cacb0711ee6d25 100644 (file)
@@ -85,7 +85,7 @@ static inline void set_pud(pud_t *dst, pud_t val)
        pud_val(*dst) = pud_val(val);
 }
 
-extern inline void pud_clear (pud_t *pud)
+static inline void pud_clear (pud_t *pud)
 {
        set_pud(pud, __pud(0));
 }
@@ -95,7 +95,7 @@ static inline void set_pgd(pgd_t *dst, pgd_t val)
        pgd_val(*dst) = pgd_val(val); 
 } 
 
-extern inline void pgd_clear (pgd_t * pgd)
+static inline void pgd_clear (pgd_t * pgd)
 {
        set_pgd(pgd, __pgd(0));
 }
@@ -375,7 +375,7 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 }
  
 /* Change flags of a PTE */
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { 
        pte_val(pte) &= _PAGE_CHG_MASK;
        pte_val(pte) |= pgprot_val(newprot);
index a8321999448f840e256d142a3cf2a62cd62db120..03837d34fba0ccdb4caab752902f1bc943755876 100644 (file)
@@ -254,7 +254,13 @@ struct thread_struct {
        u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
 } __attribute__((aligned(16)));
 
-#define INIT_THREAD  {}
+#define INIT_THREAD  { \
+       .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
+
+#define INIT_TSS  { \
+       .rsp0 = (unsigned long)&init_stack + sizeof(init_stack) \
+}
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
@@ -375,13 +381,13 @@ struct extended_sigtable {
 #define ASM_NOP_MAX 8
 
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
-extern inline void rep_nop(void)
+static inline void rep_nop(void)
 {
        __asm__ __volatile__("rep;nop": : :"memory");
 }
 
 /* Stop speculative execution */
-extern inline void sync_core(void)
+static inline void sync_core(void)
 { 
        int tmp;
        asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
index 6c813eb521f339f363a71e21caca53ba204bfcf8..dbb37b0adb43df3f2ea20d62bc4e398c9bd469be 100644 (file)
@@ -8,7 +8,6 @@
 struct cpuinfo_x86; 
 struct pt_regs;
 
-extern void get_cpu_vendor(struct cpuinfo_x86*);
 extern void start_kernel(void);
 extern void pda_init(int); 
 
@@ -75,9 +74,6 @@ extern void acpi_reserve_bootmem(void);
 
 extern void swap_low_mappings(void);
 
-extern void oops_begin(void);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char * str, struct pt_regs * regs, long err);
 extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 
@@ -94,8 +90,6 @@ extern int unhandled_signal(struct task_struct *tsk, int sig);
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void swiotlb_init(void);
 
-extern unsigned long max_mapnr;
-extern unsigned long end_pfn; 
 extern unsigned long table_start, table_end;
 
 extern int exception_trace;
index fe9b96d94815f688091d6c1318e1905d8c995ac8..f8d55798535ac4ccf06e1fc46cbc624a6b68cd76 100644 (file)
@@ -143,23 +143,23 @@ typedef struct sigaltstack {
 #undef __HAVE_ARCH_SIG_BITOPS
 #if 0
 
-extern __inline__ void sigaddset(sigset_t *set, int _sig)
+static inline void sigaddset(sigset_t *set, int _sig)
 {
        __asm__("btsq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
 }
 
-extern __inline__ void sigdelset(sigset_t *set, int _sig)
+static inline void sigdelset(sigset_t *set, int _sig)
 {
        __asm__("btrq %1,%0" : "=m"(*set) : "Ir"(_sig - 1) : "cc");
 }
 
-extern __inline__ int __const_sigismember(sigset_t *set, int _sig)
+static inline int __const_sigismember(sigset_t *set, int _sig)
 {
        unsigned long sig = _sig - 1;
        return 1 & (set->sig[sig / _NSIG_BPW] >> (sig & ~(_NSIG_BPW-1)));
 }
 
-extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
+static inline int __gen_sigismember(sigset_t *set, int _sig)
 {
        int ret;
        __asm__("btq %2,%1\n\tsbbq %0,%0"
@@ -172,7 +172,7 @@ extern __inline__ int __gen_sigismember(sigset_t *set, int _sig)
         __const_sigismember((set),(sig)) :     \
         __gen_sigismember((set),(sig)))
 
-extern __inline__ int sigfindinword(unsigned long word)
+static inline int sigfindinword(unsigned long word)
 {
        __asm__("bsfq %1,%0" : "=r"(word) : "rm"(word) : "cc");
        return word;
index de8b57b2b62b934c8bfe6cf3b0fa6fd87b8204f8..24e32611f0bf3d93bc0a41f15fa3678d3006f598 100644 (file)
@@ -72,7 +72,7 @@ static inline int num_booting_cpus(void)
 
 #define raw_smp_processor_id() read_pda(cpunumber)
 
-extern __inline int hard_smp_processor_id(void)
+static inline int hard_smp_processor_id(void)
 {
        /* we don't want to mark this access volatile - bad code generation */
        return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
index 5aeb57a3baad30b7111aa28cc6149cf891394bd5..69636831ad2f4e3f5d756ab4bbec60da5bfd18f9 100644 (file)
@@ -6,47 +6,21 @@
 #include <asm/page.h>
 #include <linux/config.h>
 
-extern int printk(const char * fmt, ...)
-       __attribute__ ((format (printf, 1, 2)));
-
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPINLOCK_MAGIC 0xdead4ead
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC_INIT    , SPINLOCK_MAGIC
-#else
-#define SPINLOCK_MAGIC_INIT    /* */
-#endif
-
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
-
-#define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
-
-/*
+ *
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  *
  * We make no fairness assumptions. They have a cost.
+ *
+ * (the type definitions are in asm/spinlock_types.h)
  */
 
-#define spin_is_locked(x)      (*(volatile signed char *)(&(x)->lock) <= 0)
-#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define __raw_spin_is_locked(x) \
+               (*(volatile signed char *)(&(x)->slock) <= 0)
 
-#define spin_lock_string \
+#define __raw_spin_lock_string \
        "\n1:\t" \
        "lock ; decb %0\n\t" \
        "js 2f\n" \
@@ -58,74 +32,40 @@ typedef struct {
        "jmp 1b\n" \
        LOCK_SECTION_END
 
-/*
- * This works. Despite all the confusion.
- * (except on PPro SMP or if we are using OOSTORE)
- * (PPro errata 66, 92)
- */
-#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
-
-#define spin_unlock_string \
+#define __raw_spin_unlock_string \
        "movb $1,%0" \
-               :"=m" (lock->lock) : : "memory"
-
-
-static inline void _raw_spin_unlock(spinlock_t *lock)
-{
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(lock->magic != SPINLOCK_MAGIC);
-       assert_spin_locked(lock);
-#endif
-       __asm__ __volatile__(
-               spin_unlock_string
-       );
-}
-
-#else
-
-#define spin_unlock_string \
-       "xchgb %b0, %1" \
-               :"=q" (oldval), "=m" (lock->lock) \
-               :"0" (oldval) : "memory"
+               :"=m" (lock->slock) : : "memory"
 
-static inline void _raw_spin_unlock(spinlock_t *lock)
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
-       char oldval = 1;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(lock->magic != SPINLOCK_MAGIC);
-       assert_spin_locked(lock);
-#endif
        __asm__ __volatile__(
-               spin_unlock_string
-       );
+               __raw_spin_lock_string
+               :"=m" (lock->slock) : : "memory");
 }
 
-#endif
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 
-static inline int _raw_spin_trylock(spinlock_t *lock)
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        char oldval;
+
        __asm__ __volatile__(
                "xchgb %b0,%1"
-               :"=q" (oldval), "=m" (lock->lock)
+               :"=q" (oldval), "=m" (lock->slock)
                :"0" (0) : "memory");
+
        return oldval > 0;
 }
 
-static inline void _raw_spin_lock(spinlock_t *lock)
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       if (lock->magic != SPINLOCK_MAGIC) {
-               printk("eip: %p\n", __builtin_return_address(0));
-               BUG();
-       }
-#endif
        __asm__ __volatile__(
-               spin_lock_string
-               :"=m" (lock->lock) : : "memory");
+               __raw_spin_unlock_string
+       );
 }
 
+#define __raw_spin_unlock_wait(lock) \
+       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -136,33 +76,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
  * can "mix" irq-safe locks - any writer needs to get a
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
- */
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_DEBUG_SPINLOCK
-       unsigned magic;
-#endif
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-
-#define RWLOCK_MAGIC   0xdeaf1eed
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define RWLOCK_MAGIC_INIT      , RWLOCK_MAGIC
-#else
-#define RWLOCK_MAGIC_INIT      /* */
-#endif
-
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
-
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-
-#define read_can_lock(x)       ((int)(x)->lock > 0)
-#define write_can_lock(x)      ((x)->lock == RW_LOCK_BIAS)
-
-/*
+ *
  * On x86, we implement read-write locks as a 32-bit counter
  * with the high bit (sign) being the "contended" bit.
  *
@@ -170,29 +84,24 @@ typedef struct {
  *
  * Changed to use the same technique as rw semaphores.  See
  * semaphore.h for details.  -ben
+ *
+ * the helpers are in arch/i386/kernel/semaphore.c
  */
-/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
 
-static inline void _raw_read_lock(rwlock_t *rw)
+#define __raw_read_can_lock(x)         ((int)(x)->lock > 0)
+#define __raw_write_can_lock(x)                ((x)->lock == RW_LOCK_BIAS)
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
        __build_read_lock(rw, "__read_lock_failed");
 }
 
-static inline void _raw_write_lock(rwlock_t *rw)
+static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
-#ifdef CONFIG_DEBUG_SPINLOCK
-       BUG_ON(rw->magic != RWLOCK_MAGIC);
-#endif
        __build_write_lock(rw, "__write_lock_failed");
 }
 
-#define _raw_read_unlock(rw)           asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
-#define _raw_write_unlock(rw)  asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
-
-static inline int _raw_read_trylock(rwlock_t *lock)
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
 {
        atomic_t *count = (atomic_t *)lock;
        atomic_dec(count);
@@ -202,7 +111,7 @@ static inline int _raw_read_trylock(rwlock_t *lock)
        return 0;
 }
 
-static inline int _raw_write_trylock(rwlock_t *lock)
+static inline int __raw_write_trylock(raw_rwlock_t *lock)
 {
        atomic_t *count = (atomic_t *)lock;
        if (atomic_sub_and_test(RW_LOCK_BIAS, count))
@@ -211,4 +120,15 @@ static inline int _raw_write_trylock(rwlock_t *lock)
        return 0;
 }
 
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+       asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+       asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0"
+                               : "=m" (rw->lock) : : "memory");
+}
+
 #endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-x86_64/spinlock_types.h b/include/asm-x86_64/spinlock_types.h
new file mode 100644 (file)
index 0000000..59efe84
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+       volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED       { 1 }
+
+typedef struct {
+       volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED         { RW_LOCK_BIAS }
+
+#endif
index 8606e170a7dc825c40d10d4101a2c721ff20f536..85348e02ad2e1f847580d21e7e8acd878f83fc4f 100644 (file)
@@ -188,7 +188,7 @@ static inline void write_cr4(unsigned long val)
 
 #define __xg(x) ((volatile long *)(x))
 
-extern inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
+static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
 {
        *ptr = val;
 }
@@ -253,19 +253,19 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
        case 2:
                __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
                                     : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        case 4:
                __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
                                     : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        case 8:
                __asm__ __volatile__(LOCK_PREFIX "cmpxchgq %1,%2"
                                     : "=a"(prev)
-                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "r"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        }
index 24ecf6a637cb47ce9a5097ad1d7f9fecf1f2b26e..f971f45d6d78b63479fa7cf48e9fb4b9efd11833 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASMx8664_TIMEX_H
 #define _ASMx8664_TIMEX_H
 
-#include <linux/config.h>
 #include <asm/8253pit.h>
 #include <asm/msr.h>
 #include <asm/vsyscall.h>
index 505b0cf906ded2658ff91da72b9d51e54e80adcc..4a9c20ea9b105d9523bb712e0b9a30d93aa30047 100644 (file)
@@ -109,6 +109,10 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st
 #define TLBSTATE_OK    1
 #define TLBSTATE_LAZY  2
 
+/* Roughly an IPI every 20MB with 4k pages for freeing page table
+   ranges. Cost is about 42k of memory for each CPU. */
+#define ARCH_FREE_PTE_NR 5350  
+
 #endif
 
 #define flush_tlb_kernel_range(start, end) flush_tlb_all()
index c1bc3fad482ed4a4388412ff300a0395f86178a1..1c603cd7e4d096389d7cf92f11b79afcc338b288 100644 (file)
@@ -13,7 +13,6 @@
 extern cpumask_t cpu_online_map;
 
 extern unsigned char cpu_to_node[];
-extern unsigned char pci_bus_to_node[];
 extern cpumask_t     node_to_cpumask[];
 
 #ifdef CONFIG_ACPI_NUMA
@@ -26,7 +25,7 @@ extern int __node_distance(int, int);
 #define parent_node(node)              (node)
 #define node_to_first_cpu(node)        (__ffs(node_to_cpumask[node]))
 #define node_to_cpumask(node)          (node_to_cpumask[node])
-#define pcibus_to_node(bus)            pci_bus_to_node[(bus)->number]
+#define pcibus_to_node(bus)            ((long)(bus->sysdata))  
 #define pcibus_to_cpumask(bus)         node_to_cpumask(pcibus_to_node(bus));
 
 /* sched_domains SD_NODE_INIT for x86_64 machines */
index 2872da23fc7ea5990feb03c110278e012aea7d15..438a3f52f839fa8161fc5c1ac8f2ec7b8f00ec89 100644 (file)
@@ -29,7 +29,6 @@ enum vsyscall_num {
 
 struct vxtime_data {
        long hpet_address;      /* HPET base address */
-       unsigned long hz;       /* HPET clocks / sec */
        int last;
        unsigned long last_tsc;
        long quot;
index 2848a5ff8349bb8a18aa91f709abdb25c12f0f52..aa4fd7fb3ce716db5fdc02680056afd130308859 100644 (file)
@@ -127,7 +127,7 @@ extern void show_regs(struct pt_regs *);
 #else  /* __ASSEMBLY__ */
 
 #ifdef __KERNEL__
-# include <asm/offsets.h>
+# include <asm/asm-offsets.h>
 #define PT_REGS_OFFSET   (KERNEL_STACK_SIZE - PT_USER_SIZE)
 #endif
 
index fc268ac923c0b9a22200515fcb54e49329a09002..06a22b83ba178d12c1d18c2148da10dc193fa0b0 100644 (file)
@@ -25,7 +25,7 @@
 
 #define _ASMLANGUAGE
 #include <asm/current.h>
-#include <asm/offsets.h>
+#include <asm/asm-offsets.h>
 #include <asm/processor.h>
 
 /*
index f7f0913cd110dfb9eb34268543f8605c6166d048..c1237aa92e38439649d1a9740985936f0e5a3c72 100644 (file)
@@ -14,8 +14,9 @@
 #define BFS_INODES_PER_BLOCK   8
 
 /* SVR4 vnode type values (bfs_inode->i_vtype) */
-#define BFS_VDIR               2
-#define BFS_VREG               1
+#define BFS_VDIR 2L
+#define BFS_VREG 1L
+
 
 /* BFS inode layout on disk */
 struct bfs_inode {
@@ -58,22 +59,22 @@ struct bfs_super_block {
        __u32 s_padding[118];
 };
 
-#define BFS_NZFILESIZE(ip) \
-        (((ip)->i_eoffset + 1) - (ip)->i_sblock * BFS_BSIZE)
-
-#define BFS_FILESIZE(ip) \
-        ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
-
-#define BFS_FILEBLOCKS(ip) \
-        ((ip)->i_sblock == 0 ? 0 : ((ip)->i_eblock + 1) - (ip)->i_sblock)
 
 #define BFS_OFF2INO(offset) \
         ((((offset) - BFS_BSIZE) / sizeof(struct bfs_inode)) + BFS_ROOT_INO)
 
 #define BFS_INO2OFF(ino) \
        ((__u32)(((ino) - BFS_ROOT_INO) * sizeof(struct bfs_inode)) + BFS_BSIZE)
+#define BFS_NZFILESIZE(ip) \
+        ((cpu_to_le32((ip)->i_eoffset) + 1) -  cpu_to_le32((ip)->i_sblock) * BFS_BSIZE)
+
+#define BFS_FILESIZE(ip) \
+        ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
 
+#define BFS_FILEBLOCKS(ip) \
+        ((ip)->i_sblock == 0 ? 0 : (cpu_to_le32((ip)->i_eblock) + 1) -  cpu_to_le32((ip)->i_sblock))
 #define BFS_UNCLEAN(bfs_sb, sb)        \
-       ((bfs_sb->s_from != -1) && (bfs_sb->s_to != -1) && !(sb->s_flags & MS_RDONLY))
+       ((cpu_to_le32(bfs_sb->s_from) != -1) && (cpu_to_le32(bfs_sb->s_to) != -1) && !(sb->s_flags & MS_RDONLY))
+
 
 #endif /* _LINUX_BFS_FS_H */
index cdaf03a14a5115333ea424944ba320b1f687bedb..6e1c79c8b6bfd0eebc33187804169d47caa2b92e 100644 (file)
@@ -314,9 +314,8 @@ void zero_fill_bio(struct bio *bio);
  * bvec_kmap_irq and bvec_kunmap_irq!!
  *
  * This function MUST be inlined - it plays with the CPU interrupt flags.
- * Hence the `extern inline'.
  */
-extern inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
+static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
 {
        unsigned long addr;
 
@@ -332,7 +331,7 @@ extern inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
        return (char *) addr + bvec->bv_offset;
 }
 
-extern inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
+static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
 {
        unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
 
@@ -345,7 +344,7 @@ extern inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
 #define bvec_kunmap_irq(buf, flags)    do { *(flags) = 0; } while (0)
 #endif
 
-extern inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
+static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx,
                                   unsigned long *flags)
 {
        return bvec_kmap_irq(bio_iovec_idx(bio, idx), flags);
diff --git a/include/linux/bit_spinlock.h b/include/linux/bit_spinlock.h
new file mode 100644 (file)
index 0000000..6b20af0
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __LINUX_BIT_SPINLOCK_H
+#define __LINUX_BIT_SPINLOCK_H
+
+/*
+ *  bit-based spin_lock()
+ *
+ * Don't use this unless you really need to: spin_lock() and spin_unlock()
+ * are significantly faster.
+ */
+static inline void bit_spin_lock(int bitnum, unsigned long *addr)
+{
+       /*
+        * Assuming the lock is uncontended, this never enters
+        * the body of the outer loop. If it is contended, then
+        * within the inner loop a non-atomic test is used to
+        * busywait with less bus contention for a good time to
+        * attempt to acquire the lock bit.
+        */
+       preempt_disable();
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+       while (test_and_set_bit(bitnum, addr)) {
+               while (test_bit(bitnum, addr)) {
+                       preempt_enable();
+                       cpu_relax();
+                       preempt_disable();
+               }
+       }
+#endif
+       __acquire(bitlock);
+}
+
+/*
+ * Return true if it was acquired
+ */
+static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
+{
+       preempt_disable();
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+       if (test_and_set_bit(bitnum, addr)) {
+               preempt_enable();
+               return 0;
+       }
+#endif
+       __acquire(bitlock);
+       return 1;
+}
+
+/*
+ *  bit-based spin_unlock()
+ */
+static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
+{
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+       BUG_ON(!test_bit(bitnum, addr));
+       smp_mb__before_clear_bit();
+       clear_bit(bitnum, addr);
+#endif
+       preempt_enable();
+       __release(bitlock);
+}
+
+/*
+ * Return true if the lock is held.
+ */
+static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
+{
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+       return test_bit(bitnum, addr);
+#elif defined CONFIG_PREEMPT
+       return preempt_count();
+#else
+       return 1;
+#endif
+}
+
+#endif /* __LINUX_BIT_SPINLOCK_H */
+
index aefa26fbae8add64ee373d9742523b534eaec7ce..efdc9b5bc05c8687380200f8a871975c91709860 100644 (file)
@@ -728,7 +728,7 @@ static inline unsigned int blksize_bits(unsigned int size)
        return bits;
 }
 
-extern inline unsigned int block_size(struct block_device *bdev)
+static inline unsigned int block_size(struct block_device *bdev)
 {
        return bdev->bd_block_size;
 }
index 63035ae67e6350881638ed2f64da672b20bda410..a404c111c937a2da3dcddba17f7aba0a63e82cb4 100644 (file)
@@ -96,7 +96,7 @@ struct changer_position {
  */
 struct changer_element_status {
        int             ces_type;
-       unsigned char   *ces_data;
+       unsigned char   __user *ces_data;
 };
 #define CESTATUS_FULL     0x01 /* full */
 #define CESTATUS_IMPEXP   0x02 /* media was imported (inserted by sysop) */
index bdedf825b04a5b7dc824b2dc8f7982a4f9bd704b..9443c084f8811d79bbd7904ff14f95fe2ecee42c 100644 (file)
@@ -1,22 +1,11 @@
 /*
  *     crc16.h - CRC-16 routine
  *
- * Implements the standard CRC-16, as used with 1-wire devices:
+ * Implements the standard CRC-16:
  *   Width 16
  *   Poly  0x8005 (x^16 + x^15 + x^2 + 1)
  *   Init  0
  *
- * For 1-wire devices, the CRC is stored inverted, LSB-first
- *
- * Example buffer with the CRC attached:
- *   31 32 33 34 35 36 37 38 39 C2 44
- *
- * The CRC over a buffer with the CRC attached is 0xB001.
- * So, if (crc16(0, buf, size) == 0xB001) then the buffer is valid.
- *
- * Refer to "Application Note 937: Book of iButton Standards" for details.
- * http://www.maxim-ic.com/appnotes.cfm/appnote_number/937
- *
  * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
  *
  * This source code is licensed under the GNU General Public License,
@@ -28,9 +17,6 @@
 
 #include <linux/types.h>
 
-#define CRC16_INIT             0
-#define CRC16_VALID            0xb001
-
 extern u16 const crc16_table[256];
 
 extern u16 crc16(u16 crc, const u8 *buffer, size_t len);
index 007c290f74d4557b38161fe1ef9378fc4919f0bb..8bf4bacb5051a2df3e8b71dde9c1c464512b851c 100644 (file)
@@ -432,7 +432,10 @@ struct dccp_sock {
        struct ccid                     *dccps_hc_rx_ccid;
        struct ccid                     *dccps_hc_tx_ccid;
        struct dccp_options_received    dccps_options_received;
+       struct timeval                  dccps_epoch;
        enum dccp_role                  dccps_role:2;
+       __u8                            dccps_hc_rx_insert_options:1;
+       __u8                            dccps_hc_tx_insert_options:1;
 };
  
 static inline struct dccp_sock *dccp_sk(const struct sock *sk)
index e60bfdac348d2d0cb4e3b13e5f858b9514a91fa8..4932ee5c77f0896d081de2ad70dadc5b122492fa 100644 (file)
@@ -19,7 +19,8 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
 
 void dma_pool_destroy(struct dma_pool *pool);
 
-void *dma_pool_alloc(struct dma_pool *pool, int mem_flags, dma_addr_t *handle);
+void *dma_pool_alloc(struct dma_pool *pool, unsigned int __nocast mem_flags,
+                    dma_addr_t *handle);
 
 void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr);
 
index c30175e8dec67fa39f7a7fb1bf753f4fa40d0dda..a415f1d93e9a4f6c6c647dd851bc19be7ef3035b 100644 (file)
@@ -70,7 +70,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name,
 
 static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
 static inline char * dmi_get_system_info(int field) { return NULL; }
-static struct dmi_device * dmi_find_device(int type, const char *name,
+static inline struct dmi_device * dmi_find_device(int type, const char *name,
        struct dmi_device *from) { return NULL; }
 
 #endif
index bc24beeed971d7a803af06bd74eb3c6ef2e300fe..82e39cd0c4fbaf5da68d79cdf6affea9da47ec20 100644 (file)
 #define FB_ACCEL_NV_20          44      /* nVidia Arch 20               */
 #define FB_ACCEL_NV_30          45      /* nVidia Arch 30               */
 #define FB_ACCEL_NV_40          46      /* nVidia Arch 40               */
+#define FB_ACCEL_XGI_VOLARI_V  47      /* XGI Volari V3XT, V5, V8      */
+#define FB_ACCEL_XGI_VOLARI_Z  48      /* XGI Volari Z7                */
 #define FB_ACCEL_NEOMAGIC_NM2070 90    /* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91    /* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92    /* NeoMagic NM2093              */
@@ -495,6 +497,9 @@ struct fb_cursor_user {
 #define FB_EVENT_BLANK                  0x08
 /*      Private modelist is to be replaced */
 #define FB_EVENT_NEW_MODELIST           0x09
+/*     The resolution of the passed in fb_info about to change and
+        all vc's should be changed         */
+#define FB_EVENT_MODE_CHANGE_ALL       0x0A
 
 struct fb_event {
        struct fb_info *info;
@@ -820,13 +825,29 @@ extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
                                u32 height, u32 shift_high, u32 shift_low, u32 mod);
 extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height);
 extern void fb_set_suspend(struct fb_info *info, int state);
-extern int fb_get_color_depth(struct fb_var_screeninfo *var);
+extern int fb_get_color_depth(struct fb_var_screeninfo *var,
+                             struct fb_fix_screeninfo *fix);
 extern int fb_get_options(char *name, char **option);
 extern int fb_new_modelist(struct fb_info *info);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
 
+static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
+                                          u8 *src, u32 s_pitch, u32 height)
+{
+       int i, j;
+
+       d_pitch -= s_pitch;
+
+       for (i = height; i--; ) {
+               /* s_pitch is a few bytes at the most, memcpy is suboptimal */
+               for (j = 0; j < s_pitch; j++)
+                       *dst++ = *src++;
+               dst += d_pitch;
+       }
+}
+
 /* drivers/video/fbsysfs.c */
 extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
 extern void framebuffer_release(struct fb_info *info);
@@ -856,8 +877,11 @@ extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
 extern int fb_validate_mode(const struct fb_var_screeninfo *var,
                            struct fb_info *info);
 extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
-extern void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs);
+extern const unsigned char *fb_firmware_edid(struct device *device);
+extern void fb_edid_to_monspecs(unsigned char *edid,
+                               struct fb_monspecs *specs);
 extern void fb_destroy_modedb(struct fb_videomode *modedb);
+extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
index 5206beb9a80e562df9377e37a2cad4cb0b8e016f..f5bbd4c508b3da00b3af27dc20f2178996cc9496 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/posix_types.h>
 #include <linux/compiler.h>
 #include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 
 /*
  * The default fd array needs to be at least BITS_PER_LONG,
  */
 #define NR_OPEN_DEFAULT BITS_PER_LONG
 
+struct fdtable {
+       unsigned int max_fds;
+       int max_fdset;
+       int next_fd;
+       struct file ** fd;      /* current fd array */
+       fd_set *close_on_exec;
+       fd_set *open_fds;
+       struct rcu_head rcu;
+       struct files_struct *free_files;
+       struct fdtable *next;
+};
+
 /*
  * Open file table structure
  */
 struct files_struct {
         atomic_t count;
         spinlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */
-        int max_fds;
-        int max_fdset;
-        int next_fd;
-        struct file ** fd;      /* current fd array */
-        fd_set *close_on_exec;
-        fd_set *open_fds;
+       struct fdtable *fdt;
+       struct fdtable fdtab;
         fd_set close_on_exec_init;
         fd_set open_fds_init;
         struct file * fd_array[NR_OPEN_DEFAULT];
 };
 
+#define files_fdtable(files) (rcu_dereference((files)->fdt))
+
 extern void FASTCALL(__fput(struct file *));
 extern void FASTCALL(fput(struct file *));
 
@@ -59,13 +70,16 @@ extern fd_set *alloc_fdset(int);
 extern void free_fdset(fd_set *, int);
 
 extern int expand_files(struct files_struct *, int nr);
+extern void free_fdtable(struct fdtable *fdt);
+extern void __init files_defer_init(void);
 
 static inline struct file * fcheck_files(struct files_struct *files, unsigned int fd)
 {
        struct file * file = NULL;
+       struct fdtable *fdt = files_fdtable(files);
 
-       if (fd < files->max_fds)
-               file = files->fd[fd];
+       if (fd < fdt->max_fds)
+               file = rcu_dereference(fdt->fd[fd]);
        return file;
 }
 
index fd93ab7da905041938a7e59473d086d4657a152b..e0b77c5af9a02aadab2a1fcd2e967c92c402ce16 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/limits.h>
 #include <linux/ioctl.h>
+#include <linux/rcuref.h>
 
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
@@ -597,12 +598,13 @@ struct file {
        spinlock_t              f_ep_lock;
 #endif /* #ifdef CONFIG_EPOLL */
        struct address_space    *f_mapping;
+       struct rcu_head         f_rcuhead;
 };
 extern spinlock_t files_lock;
 #define file_list_lock() spin_lock(&files_lock);
 #define file_list_unlock() spin_unlock(&files_lock);
 
-#define get_file(x)    atomic_inc(&(x)->f_count)
+#define get_file(x)    rcuref_inc(&(x)->f_count)
 #define file_count(x)  atomic_read(&(x)->f_count)
 
 #define        MAX_NON_LFS     ((1UL<<31) - 1)
@@ -1507,8 +1509,6 @@ extern void do_generic_mapping_read(struct address_space *mapping,
                                    loff_t *, read_descriptor_t *, read_actor_t);
 extern void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
-extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
-       const struct iovec *iov, loff_t offset, unsigned long nr_segs);
 extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
        unsigned long nr_segs, loff_t *ppos);
 ssize_t generic_file_writev(struct file *filp, const struct iovec *iov, 
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
new file mode 100644 (file)
index 0000000..acbeb96
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+    FUSE: Filesystem in Userspace
+    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+
+    This program can be distributed under the terms of the GNU GPL.
+    See the file COPYING.
+*/
+
+/* This file defines the kernel interface of FUSE */
+
+#include <asm/types.h>
+
+/** Version number of this interface */
+#define FUSE_KERNEL_VERSION 7
+
+/** Minor version number of this interface */
+#define FUSE_KERNEL_MINOR_VERSION 2
+
+/** The node ID of the root inode */
+#define FUSE_ROOT_ID 1
+
+/** The major number of the fuse character device */
+#define FUSE_MAJOR 10
+
+/** The minor number of the fuse character device */
+#define FUSE_MINOR 229
+
+/* Make sure all structures are padded to 64bit boundary, so 32bit
+   userspace works under 64bit kernels */
+
+struct fuse_attr {
+       __u64   ino;
+       __u64   size;
+       __u64   blocks;
+       __u64   atime;
+       __u64   mtime;
+       __u64   ctime;
+       __u32   atimensec;
+       __u32   mtimensec;
+       __u32   ctimensec;
+       __u32   mode;
+       __u32   nlink;
+       __u32   uid;
+       __u32   gid;
+       __u32   rdev;
+};
+
+struct fuse_kstatfs {
+       __u64   blocks;
+       __u64   bfree;
+       __u64   bavail;
+       __u64   files;
+       __u64   ffree;
+       __u32   bsize;
+       __u32   namelen;
+};
+
+#define FATTR_MODE     (1 << 0)
+#define FATTR_UID      (1 << 1)
+#define FATTR_GID      (1 << 2)
+#define FATTR_SIZE     (1 << 3)
+#define FATTR_ATIME    (1 << 4)
+#define FATTR_MTIME    (1 << 5)
+#define FATTR_CTIME    (1 << 6)
+
+/**
+ * Flags returned by the OPEN request
+ *
+ * FOPEN_DIRECT_IO: bypass page cache for this open file
+ * FOPEN_KEEP_CACHE: don't invalidate the data cache on open
+ */
+#define FOPEN_DIRECT_IO                (1 << 0)
+#define FOPEN_KEEP_CACHE       (1 << 1)
+
+enum fuse_opcode {
+       FUSE_LOOKUP        = 1,
+       FUSE_FORGET        = 2,  /* no reply */
+       FUSE_GETATTR       = 3,
+       FUSE_SETATTR       = 4,
+       FUSE_READLINK      = 5,
+       FUSE_SYMLINK       = 6,
+       FUSE_MKNOD         = 8,
+       FUSE_MKDIR         = 9,
+       FUSE_UNLINK        = 10,
+       FUSE_RMDIR         = 11,
+       FUSE_RENAME        = 12,
+       FUSE_LINK          = 13,
+       FUSE_OPEN          = 14,
+       FUSE_READ          = 15,
+       FUSE_WRITE         = 16,
+       FUSE_STATFS        = 17,
+       FUSE_RELEASE       = 18,
+       FUSE_FSYNC         = 20,
+       FUSE_SETXATTR      = 21,
+       FUSE_GETXATTR      = 22,
+       FUSE_LISTXATTR     = 23,
+       FUSE_REMOVEXATTR   = 24,
+       FUSE_FLUSH         = 25,
+       FUSE_INIT          = 26,
+       FUSE_OPENDIR       = 27,
+       FUSE_READDIR       = 28,
+       FUSE_RELEASEDIR    = 29,
+       FUSE_FSYNCDIR      = 30
+};
+
+/* Conservative buffer size for the client */
+#define FUSE_MAX_IN 8192
+
+#define FUSE_NAME_MAX 1024
+#define FUSE_SYMLINK_MAX 4096
+#define FUSE_XATTR_SIZE_MAX 4096
+
+struct fuse_entry_out {
+       __u64   nodeid;         /* Inode ID */
+       __u64   generation;     /* Inode generation: nodeid:gen must
+                                  be unique for the fs's lifetime */
+       __u64   entry_valid;    /* Cache timeout for the name */
+       __u64   attr_valid;     /* Cache timeout for the attributes */
+       __u32   entry_valid_nsec;
+       __u32   attr_valid_nsec;
+       struct fuse_attr attr;
+};
+
+struct fuse_forget_in {
+       __u64   nlookup;
+};
+
+struct fuse_attr_out {
+       __u64   attr_valid;     /* Cache timeout for the attributes */
+       __u32   attr_valid_nsec;
+       __u32   dummy;
+       struct fuse_attr attr;
+};
+
+struct fuse_mknod_in {
+       __u32   mode;
+       __u32   rdev;
+};
+
+struct fuse_mkdir_in {
+       __u32   mode;
+       __u32   padding;
+};
+
+struct fuse_rename_in {
+       __u64   newdir;
+};
+
+struct fuse_link_in {
+       __u64   oldnodeid;
+};
+
+struct fuse_setattr_in {
+       __u32   valid;
+       __u32   padding;
+       struct fuse_attr attr;
+};
+
+struct fuse_open_in {
+       __u32   flags;
+       __u32   padding;
+};
+
+struct fuse_open_out {
+       __u64   fh;
+       __u32   open_flags;
+       __u32   padding;
+};
+
+struct fuse_release_in {
+       __u64   fh;
+       __u32   flags;
+       __u32   padding;
+};
+
+struct fuse_flush_in {
+       __u64   fh;
+       __u32   flush_flags;
+       __u32   padding;
+};
+
+struct fuse_read_in {
+       __u64   fh;
+       __u64   offset;
+       __u32   size;
+       __u32   padding;
+};
+
+struct fuse_write_in {
+       __u64   fh;
+       __u64   offset;
+       __u32   size;
+       __u32   write_flags;
+};
+
+struct fuse_write_out {
+       __u32   size;
+       __u32   padding;
+};
+
+struct fuse_statfs_out {
+       struct fuse_kstatfs st;
+};
+
+struct fuse_fsync_in {
+       __u64   fh;
+       __u32   fsync_flags;
+       __u32   padding;
+};
+
+struct fuse_setxattr_in {
+       __u32   size;
+       __u32   flags;
+};
+
+struct fuse_getxattr_in {
+       __u32   size;
+       __u32   padding;
+};
+
+struct fuse_getxattr_out {
+       __u32   size;
+       __u32   padding;
+};
+
+struct fuse_init_in_out {
+       __u32   major;
+       __u32   minor;
+};
+
+struct fuse_in_header {
+       __u32   len;
+       __u32   opcode;
+       __u64   unique;
+       __u64   nodeid;
+       __u32   uid;
+       __u32   gid;
+       __u32   pid;
+       __u32   padding;
+};
+
+struct fuse_out_header {
+       __u32   len;
+       __s32   error;
+       __u64   unique;
+};
+
+struct fuse_dirent {
+       __u64   ino;
+       __u64   off;
+       __u32   namelen;
+       __u32   type;
+       char name[0];
+};
+
+#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
+#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
+#define FUSE_DIRENT_SIZE(d) \
+       FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
index bd32b79d6295fe7cb4ff3239be932df09a63972b..304aaedea305dadd18748fda4cdd96d6e2408ace 100644 (file)
@@ -198,27 +198,43 @@ struct in6_flowlabel_req
  * MCAST_MSFILTER              48
  */
 
-/* RFC3542 advanced socket options (50-67) */
-#define IPV6_RECVPKTINFO       50
-#define IPV6_PKTINFO           51
-#if 0
-#define IPV6_RECVPATHMTU       52
-#define IPV6_PATHMTU           53
-#define IPV6_DONTFRAG          54
-#define IPV6_USE_MIN_MTU       55
-#endif
-#define IPV6_RECVHOPOPTS       56
-#define IPV6_HOPOPTS           57
-#if 0
-#define IPV6_RECVRTHDRDSTOPTS  58      /* Unused, see net/ipv6/datagram.c */
+/*
+ * Advanced API (RFC3542) (1)
+ *
+ * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c.
+ */
+
+#define IPV6_RECVPKTINFO       49
+#define IPV6_PKTINFO           50
+#define IPV6_RECVHOPLIMIT      51
+#define IPV6_HOPLIMIT          52
+#define IPV6_RECVHOPOPTS       53
+#define IPV6_HOPOPTS           54
+#define IPV6_RTHDRDSTOPTS      55
+#define IPV6_RECVRTHDR         56
+#define IPV6_RTHDR             57
+#define IPV6_RECVDSTOPTS       58
+#define IPV6_DSTOPTS           59
+#if 0  /* not yet */
+#define IPV6_RECVPATHMTU       60
+#define IPV6_PATHMTU           61
+#define IPV6_DONTFRAG          62
+#define IPV6_USE_MIN_MTU       63
 #endif
-#define IPV6_RTHDRDSTOPTS      59
-#define IPV6_RECVRTHDR         60
-#define IPV6_RTHDR             61
-#define IPV6_RECVDSTOPTS       62
-#define IPV6_DSTOPTS           63
-#define IPV6_RECVHOPLIMIT      64
-#define IPV6_HOPLIMIT          65
+
+/*
+ * Netfilter
+ *
+ * Following socket options are used in ip6_tables;
+ * see include/linux/netfilter_ipv6/ip6_tables.h.
+ *
+ * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO              64
+ * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES      65
+ */
+
+/*
+ * Advanced API (RFC3542) (2)
+ */
 #define IPV6_RECVTCLASS                66
 #define IPV6_TCLASS            67
 
index c727c195a91a87cc0015abb05d7ed8660cf63453..68ab5f2ab9cdb35bd8249f03b7e3b5b0bc54e443 100644 (file)
@@ -2,17 +2,27 @@
 #define _LINUX__INIT_TASK_H
 
 #include <linux/file.h>
+#include <linux/rcupdate.h>
 
-#define INIT_FILES \
-{                                                      \
-       .count          = ATOMIC_INIT(1),               \
-       .file_lock      = SPIN_LOCK_UNLOCKED,           \
+#define INIT_FDTABLE \
+{                                                      \
        .max_fds        = NR_OPEN_DEFAULT,              \
        .max_fdset      = __FD_SETSIZE,                 \
        .next_fd        = 0,                            \
        .fd             = &init_files.fd_array[0],      \
        .close_on_exec  = &init_files.close_on_exec_init, \
        .open_fds       = &init_files.open_fds_init,    \
+       .rcu            = RCU_HEAD_INIT,                \
+       .free_files     = NULL,                         \
+       .next           = NULL,                         \
+}
+
+#define INIT_FILES \
+{                                                      \
+       .count          = ATOMIC_INIT(1),               \
+       .file_lock      = SPIN_LOCK_UNLOCKED,           \
+       .fdt            = &init_files.fdtab,            \
+       .fdtab          = INIT_FDTABLE,                 \
        .close_on_exec_init = { { 0, } },               \
        .open_fds_init  = { { 0, } },                   \
        .fd_array       = { NULL, }                     \
index 4767e5429534dff11c004923b5a3ee9827bcac50..e8c296ff6257adeccdd9d60245f463d1ea0255a3 100644 (file)
@@ -289,6 +289,8 @@ struct input_absinfo {
 #define KEY_SCROLLDOWN         178
 #define KEY_KPLEFTPAREN                179
 #define KEY_KPRIGHTPAREN       180
+#define KEY_NEW                        181
+#define KEY_REDO               182
 
 #define KEY_F13                        183
 #define KEY_F14                        184
@@ -335,6 +337,12 @@ struct input_absinfo {
 #define KEY_KBDILLUMDOWN       229
 #define KEY_KBDILLUMUP         230
 
+#define KEY_SEND               231
+#define KEY_REPLY              232
+#define KEY_FORWARDMAIL                233
+#define KEY_SAVE               234
+#define KEY_DOCUMENTS          235
+
 #define KEY_UNKNOWN            240
 
 #define BTN_MISC               0x100
index d99e7aeb7d338a9fde859840ab4aff555f20e488..0a90205184b0b4511776604fd0b37a6fc0cf6bc1 100644 (file)
@@ -57,6 +57,11 @@ extern void disable_irq(unsigned int irq);
 extern void enable_irq(unsigned int irq);
 #endif
 
+#ifndef __ARCH_SET_SOFTIRQ_PENDING
+#define set_softirq_pending(x) (local_softirq_pending() = (x))
+#define or_softirq_pending(x)  (local_softirq_pending() |= (x))
+#endif
+
 /*
  * Temporary defines for UP kernels, until all code gets fixed.
  */
@@ -123,7 +128,7 @@ struct softirq_action
 asmlinkage void do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
 extern void softirq_init(void);
-#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
+#define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
 extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
 extern void FASTCALL(raise_softirq(unsigned int nr));
 
index 6c5f7b39a4b0135fc479fed6979f267d681755f2..bb6f88e14061ed6d3543a632aebb7b616fca0a1e 100644 (file)
@@ -68,7 +68,7 @@ struct ipv6_opt_hdr {
 
 struct rt0_hdr {
        struct ipv6_rt_hdr      rt_hdr;
-       __u32                   bitmap;         /* strict/loose bit map */
+       __u32                   reserved;
        struct in6_addr         addr[0];
 
 #define rt0_type               rt_hdr.type
index 84321a4cac93a1e942a4df994f28dbf44aeeec86..de097269bd7f00596f6da5059876e6d7305c1c56 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/buffer_head.h>
 #include <linux/journal-head.h>
 #include <linux/stddef.h>
+#include <linux/bit_spinlock.h>
 #include <asm/semaphore.h>
 #endif
 
index d7a2555a886c35edfe157f763236749d05e9f0e5..6acfdbba734b17f554a089ca30f27ef12102789e 100644 (file)
@@ -254,23 +254,23 @@ static inline u64 get_jiffies_64(void)
  */
 static inline unsigned int jiffies_to_msecs(const unsigned long j)
 {
-#if HZ <= 1000 && !(1000 % HZ)
-       return (1000 / HZ) * j;
-#elif HZ > 1000 && !(HZ % 1000)
-       return (j + (HZ / 1000) - 1)/(HZ / 1000);
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+       return (MSEC_PER_SEC / HZ) * j;
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+       return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
 #else
-       return (j * 1000) / HZ;
+       return (j * MSEC_PER_SEC) / HZ;
 #endif
 }
 
 static inline unsigned int jiffies_to_usecs(const unsigned long j)
 {
-#if HZ <= 1000000 && !(1000000 % HZ)
-       return (1000000 / HZ) * j;
-#elif HZ > 1000000 && !(HZ % 1000000)
-       return (j + (HZ / 1000000) - 1)/(HZ / 1000000);
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+       return (USEC_PER_SEC / HZ) * j;
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+       return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC);
 #else
-       return (j * 1000000) / HZ;
+       return (j * USEC_PER_SEC) / HZ;
 #endif
 }
 
@@ -278,12 +278,12 @@ static inline unsigned long msecs_to_jiffies(const unsigned int m)
 {
        if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
                return MAX_JIFFY_OFFSET;
-#if HZ <= 1000 && !(1000 % HZ)
-       return (m + (1000 / HZ) - 1) / (1000 / HZ);
-#elif HZ > 1000 && !(HZ % 1000)
-       return m * (HZ / 1000);
+#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
+       return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ);
+#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC)
+       return m * (HZ / MSEC_PER_SEC);
 #else
-       return (m * HZ + 999) / 1000;
+       return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC;
 #endif
 }
 
@@ -291,12 +291,12 @@ static inline unsigned long usecs_to_jiffies(const unsigned int u)
 {
        if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
                return MAX_JIFFY_OFFSET;
-#if HZ <= 1000000 && !(1000000 % HZ)
-       return (u + (1000000 / HZ) - 1) / (1000000 / HZ);
-#elif HZ > 1000000 && !(HZ % 1000000)
-       return u * (HZ / 1000000);
+#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
+       return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ);
+#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC)
+       return u * (HZ / USEC_PER_SEC);
 #else
-       return (u * HZ + 999999) / 1000000;
+       return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC;
 #endif
 }
 
index 6caaba0af46975f51b4a9ca7836fb31bc08dd192..7349058ed7789b6417cd198203371b3463267880 100644 (file)
@@ -315,8 +315,11 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s
                pci_bus_add_devices(root_bus);
        return root_bus;
 }
+struct pci_bus *pci_create_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
+struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
 int pci_scan_slot(struct pci_bus *bus, int devfn);
 struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
+void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
 void pci_bus_add_device(struct pci_dev *dev);
 void pci_read_bridge_bases(struct pci_bus *child);
@@ -326,6 +329,7 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_remove_bus_device(struct pci_dev *dev);
+void pci_setup_cardbus(struct pci_bus *bus);
 
 /* Generic PCI functions exported to card drivers */
 
@@ -391,8 +395,8 @@ int pci_assign_resource(struct pci_dev *dev, int i);
 void pci_restore_bars(struct pci_dev *dev);
 
 /* ROM control related routines */
-void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size);
-void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
+void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
+void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 void pci_remove_rom(struct pci_dev *pdev);
 
index 8081a281fa5eb0a195e8b13cc8110c531a2f90f0..9c51917b1cce1f9146ec4b564cb43780cc3f3b21 100644 (file)
@@ -24,7 +24,7 @@
 
 struct radix_tree_root {
        unsigned int            height;
-       int                     gfp_mask;
+       unsigned int            gfp_mask;
        struct radix_tree_node  *rnode;
 };
 
@@ -50,7 +50,7 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                        unsigned long first_index, unsigned int max_items);
-int radix_tree_preload(int gfp_mask);
+int radix_tree_preload(unsigned int __nocast gfp_mask);
 void radix_tree_init(void);
 void *radix_tree_tag_set(struct radix_tree_root *root,
                        unsigned long index, int tag);
index 4bf1659f8aa87df1e9aad302f17c008f10850bd5..9de99198caf10a353a69e8a9fef32ed3c9d8c36d 100644 (file)
@@ -7,7 +7,7 @@
 #define BITMAP_H 1
 
 #define BITMAP_MAJOR 3
-#define BITMAP_MINOR 38
+#define BITMAP_MINOR 39
 
 /*
  * in-memory bitmap:
@@ -147,8 +147,9 @@ typedef struct bitmap_super_s {
        __u32 state;        /* 48  bitmap state information */
        __u32 chunksize;    /* 52  the bitmap chunk size in bytes */
        __u32 daemon_sleep; /* 56  seconds between disk flushes */
+       __u32 write_behind; /* 60  number of outstanding write-behind writes */
 
-       __u8  pad[256 - 60]; /* set to zero */
+       __u8  pad[256 - 64]; /* set to zero */
 } bitmap_super_t;
 
 /* notes:
@@ -226,6 +227,9 @@ struct bitmap {
 
        unsigned long flags;
 
+       unsigned long max_write_behind; /* write-behind mode */
+       atomic_t behind_writes;
+
        /*
         * the bitmap daemon - periodically wakes up and sweeps the bitmap
         * file, cleaning up bits and flushing out pages to disk as necessary
@@ -260,9 +264,10 @@ int  bitmap_setallbits(struct bitmap *bitmap);
 void bitmap_write_all(struct bitmap *bitmap);
 
 /* these are exported */
-int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
-void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
-                    int success);
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
+                       unsigned long sectors, int behind);
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset,
+                       unsigned long sectors, int success, int behind);
 int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int degraded);
 void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
 void bitmap_close_sync(struct bitmap *bitmap);
index e04c4fe45b533303e1acc30f4d64c8a3cf987d36..7eaf290e10e75d344a78174e3602b38e3179c400 100644 (file)
@@ -14,8 +14,8 @@ typedef struct dev_info dev_info_t;
 struct linear_private_data
 {
        dev_info_t              **hash_table;
-       dev_info_t              *smallest;
-       int                     nr_zones;
+       sector_t                hash_spacing;
+       int                     preshift; /* shift before dividing by hash_spacing */
        dev_info_t              disks[0];
 };
 
index 8c14ba565a45b95093b0a65e113bda2898f1d358..ebce949b14432c4e3e157da8c32d74336e9de5e1 100644 (file)
@@ -85,70 +85,6 @@ typedef struct mdk_rdev_s mdk_rdev_t;
 
 #define MAX_CHUNK_SIZE (4096*1024)
 
-/*
- * default readahead
- */
-
-static inline int disk_faulty(mdp_disk_t * d)
-{
-       return d->state & (1 << MD_DISK_FAULTY);
-}
-
-static inline int disk_active(mdp_disk_t * d)
-{
-       return d->state & (1 << MD_DISK_ACTIVE);
-}
-
-static inline int disk_sync(mdp_disk_t * d)
-{
-       return d->state & (1 << MD_DISK_SYNC);
-}
-
-static inline int disk_spare(mdp_disk_t * d)
-{
-       return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
-}
-
-static inline int disk_removed(mdp_disk_t * d)
-{
-       return d->state & (1 << MD_DISK_REMOVED);
-}
-
-static inline void mark_disk_faulty(mdp_disk_t * d)
-{
-       d->state |= (1 << MD_DISK_FAULTY);
-}
-
-static inline void mark_disk_active(mdp_disk_t * d)
-{
-       d->state |= (1 << MD_DISK_ACTIVE);
-}
-
-static inline void mark_disk_sync(mdp_disk_t * d)
-{
-       d->state |= (1 << MD_DISK_SYNC);
-}
-
-static inline void mark_disk_spare(mdp_disk_t * d)
-{
-       d->state = 0;
-}
-
-static inline void mark_disk_removed(mdp_disk_t * d)
-{
-       d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
-}
-
-static inline void mark_disk_inactive(mdp_disk_t * d)
-{
-       d->state &= ~(1 << MD_DISK_ACTIVE);
-}
-
-static inline void mark_disk_nonsync(mdp_disk_t * d)
-{
-       d->state &= ~(1 << MD_DISK_SYNC);
-}
-
 /*
  * MD's 'extended' device
  */
@@ -166,6 +102,7 @@ struct mdk_rdev_s
        int             sb_loaded;
        sector_t        data_offset;    /* start of data in array */
        sector_t        sb_offset;
+       int             sb_size;        /* bytes in the superblock */
        int             preferred_minor;        /* autorun support */
 
        /* A device can be in one of three states based on two flags:
@@ -181,6 +118,9 @@ struct mdk_rdev_s
        int faulty;                     /* if faulty do not issue IO requests */
        int in_sync;                    /* device is a full member of the array */
 
+       unsigned long   flags;          /* Should include faulty and in_sync here. */
+#define        WriteMostly     4               /* Avoid reading if at all possible */
+
        int desc_nr;                    /* descriptor index in the superblock */
        int raid_disk;                  /* role of device in array */
        int saved_raid_disk;            /* role that device used to have in the
@@ -272,12 +212,19 @@ struct mddev_s
        atomic_t                        writes_pending; 
        request_queue_t                 *queue; /* for plugging ... */
 
+       atomic_t                        write_behind; /* outstanding async IO */
+       unsigned int                    max_write_behind; /* 0 = sync */
+
        struct bitmap                   *bitmap; /* the bitmap for the device */
        struct file                     *bitmap_file; /* the bitmap file */
        long                            bitmap_offset; /* offset from superblock of
                                                        * start of bitmap. May be
                                                        * negative, but not '0'
                                                        */
+       long                            default_bitmap_offset; /* this is the offset to use when
+                                                               * hot-adding a bitmap.  It should
+                                                               * eventually be settable by sysfs.
+                                                               */
 
        struct list_head                all_mddevs;
 };
@@ -314,6 +261,12 @@ struct mdk_personality_s
        int (*resize) (mddev_t *mddev, sector_t sectors);
        int (*reshape) (mddev_t *mddev, int raid_disks);
        int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
+       /* quiesce moves between quiescence states
+        * 0 - fully active
+        * 1 - no new requests allowed
+        * others - reserved
+        */
+       void (*quiesce) (mddev_t *mddev, int state);
 };
 
 
index dc65cd4354942d4efd7b31bd9eba4bba7c8bf405..c100fa5d4bfa0f44b4a778d1317d420ca7d2d994 100644 (file)
 #define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
 #define MD_DISK_REMOVED                3 /* disk is in sync with the raid set */
 
+#define        MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
+                                  * read requests will only be sent here in
+                                  * dire need
+                                  */
+
 typedef struct mdp_device_descriptor_s {
        __u32 number;           /* 0 Device number in the entire set          */
        __u32 major;            /* 1 Device major number                      */
@@ -193,7 +198,7 @@ struct mdp_superblock_1 {
 
        __u64   ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
        __u32   level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
-       __u32   layout;         /* only for raid5 currently */
+       __u32   layout;         /* only for raid5 and raid10 currently */
        __u64   size;           /* used size of component devices, in 512byte sectors */
 
        __u32   chunksize;      /* in 512byte sectors */
@@ -212,7 +217,9 @@ struct mdp_superblock_1 {
        __u32   dev_number;     /* permanent identifier of this  device - not role in raid */
        __u32   cnt_corrected_read; /* number of read errors that were corrected by re-writing */
        __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
-       __u8    pad2[64-56];    /* set to 0 when writing */
+       __u8    devflags;       /* per-device flags.  Only one defined...*/
+#define        WriteMostly1    1       /* mask for writemostly flag in above */
+       __u8    pad2[64-57];    /* set to 0 when writing */
 
        /* array state information - 64 bytes */
        __u64   utime;          /* 40 bits second, 24 btes microseconds */
@@ -231,5 +238,10 @@ struct mdp_superblock_1 {
        __u16   dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
 };
 
+/* feature_map bits */
+#define MD_FEATURE_BITMAP_OFFSET       1
+
+#define        MD_FEATURE_ALL                  1
+
 #endif 
 
index 9d93cf12e8901d7cb34f8013d290eb4e8e4d1f1f..60e19b667548feccf6d8dd5cac96ab0c3420c3a5 100644 (file)
@@ -80,6 +80,9 @@ struct r1bio_s {
        atomic_t                remaining; /* 'have we finished' count,
                                            * used from IRQ handlers
                                            */
+       atomic_t                behind_remaining; /* number of write-behind ios remaining
+                                                * in this BehindIO request
+                                                */
        sector_t                sector;
        int                     sectors;
        unsigned long           state;
@@ -107,4 +110,14 @@ struct r1bio_s {
 #define        R1BIO_Uptodate  0
 #define        R1BIO_IsSync    1
 #define        R1BIO_Degraded  2
+#define        R1BIO_BehindIO   3
+/* For write-behind requests, we call bi_end_io when
+ * the last non-write-behind device completes, providing
+ * any write was successful.  Otherwise we call when
+ * any write-behind write succeeds, otherwise we call
+ * with failure when last write completes (and all failed).
+ * Record that bi_end_io was called with this flag...
+ */
+#define        R1BIO_Returned 4
+
 #endif
index d63ddcb4afadf4000cdb1bb775abe5b9dc392d70..176fc653c284711d2e6b627c348d9e5c66d2cdf7 100644 (file)
@@ -134,6 +134,7 @@ struct stripe_head {
        unsigned long           state;                  /* state flags */
        atomic_t                count;                  /* nr of active thread/requests */
        spinlock_t              lock;
+       int                     bm_seq; /* sequence number for bitmap flushes */
        struct r5dev {
                struct bio      req;
                struct bio_vec  vec;
@@ -165,12 +166,13 @@ struct stripe_head {
 /*
  * Stripe state
  */
-#define STRIPE_ERROR           1
 #define STRIPE_HANDLE          2
 #define        STRIPE_SYNCING          3
 #define        STRIPE_INSYNC           4
 #define        STRIPE_PREREAD_ACTIVE   5
 #define        STRIPE_DELAYED          6
+#define        STRIPE_DEGRADED         7
+#define        STRIPE_BIT_DELAY        8
 
 /*
  * Plugging:
@@ -210,10 +212,20 @@ struct raid5_private_data {
 
        struct list_head        handle_list; /* stripes needing handling */
        struct list_head        delayed_list; /* stripes that have plugged requests */
+       struct list_head        bitmap_list; /* stripes delaying awaiting bitmap update */
        atomic_t                preread_active_stripes; /* stripes with scheduled io */
 
        char                    cache_name[20];
        kmem_cache_t            *slab_cache; /* for allocating stripes */
+
+       int                     seq_flush, seq_write;
+       int                     quiesce;
+
+       int                     fullsync;  /* set to 1 if a full sync is needed,
+                                           * (fresh device added).
+                                           * Cleared when a sync completes.
+                                           */
+
        /*
         * Free stripes pool
         */
index fd276adf0fd5b5ad414ff3119cf19e5418737537..4e65eb44adfd0914e66b461cceea6356eeb2458f 100644 (file)
@@ -52,8 +52,8 @@ struct rcu_head {
        void (*func)(struct rcu_head *head);
 };
 
-#define RCU_HEAD_INIT(head) { .next = NULL, .func = NULL }
-#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT(head)
+#define RCU_HEAD_INIT  { .next = NULL, .func = NULL }
+#define RCU_HEAD(head) struct rcu_head head = RCU_HEAD_INIT
 #define INIT_RCU_HEAD(ptr) do { \
        (ptr)->next = NULL; (ptr)->func = NULL; \
 } while (0)
diff --git a/include/linux/rcuref.h b/include/linux/rcuref.h
new file mode 100644 (file)
index 0000000..e1adbba
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * rcuref.h
+ *
+ * Reference counting for elements of lists/arrays protected by
+ * RCU.
+ *
+ * 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) IBM Corporation, 2005
+ *
+ * Author: Dipankar Sarma <dipankar@in.ibm.com>
+ *        Ravikiran Thirumalai <kiran_th@gmail.com>
+ *
+ * See Documentation/RCU/rcuref.txt for detailed user guide.
+ *
+ */
+
+#ifndef _RCUREF_H_
+#define _RCUREF_H_
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+/*
+ * These APIs work on traditional atomic_t counters used in the
+ * kernel for reference counting. Under special circumstances
+ * where a lock-free get() operation races with a put() operation
+ * these APIs can be used. See Documentation/RCU/rcuref.txt.
+ */
+
+#ifdef __HAVE_ARCH_CMPXCHG
+
+/**
+ * rcuref_inc - increment refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference
+ * in a lock-free reader-side critical section.
+ */
+static inline void rcuref_inc(atomic_t *rcuref)
+{
+       atomic_inc(rcuref);
+}
+
+/**
+ * rcuref_dec - decrement refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference
+ * in a lock-free reader-side critical section.
+ */
+static inline void rcuref_dec(atomic_t *rcuref)
+{
+       atomic_dec(rcuref);
+}
+
+/**
+ * rcuref_dec_and_test - decrement refcount for object and test
+ * @rcuref: reference counter in the object.
+ * @release: pointer to the function that will clean up the object
+ *          when the last reference to the object is released.
+ *          This pointer is required.
+ *
+ * Decrement the refcount, and if 0, return 1. Else return 0.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference
+ * in a lock-free reader-side critical section.
+ */
+static inline int rcuref_dec_and_test(atomic_t *rcuref)
+{
+       return atomic_dec_and_test(rcuref);
+}
+
+/*
+ * cmpxchg is needed on UP too, if deletions to the list/array can happen
+ * in interrupt context.
+ */
+
+/**
+ * rcuref_inc_lf - Take reference to an object in a read-side
+ * critical section protected by RCU.
+ * @rcuref: reference counter in the object in question.
+ *
+ * Try and increment the refcount by 1.  The increment might fail if
+ * the reference counter has been through a 1 to 0 transition and
+ * is no longer part of the lock-free list.
+ * Returns non-zero on successful increment and zero otherwise.
+ */
+static inline int rcuref_inc_lf(atomic_t *rcuref)
+{
+       int c, old;
+       c = atomic_read(rcuref);
+       while (c && (old = cmpxchg(&rcuref->counter, c, c + 1)) != c)
+               c = old;
+       return c;
+}
+
+#else                          /* !__HAVE_ARCH_CMPXCHG */
+
+extern spinlock_t __rcuref_hash[];
+
+/*
+ * Use a hash table of locks to protect the reference count
+ * since cmpxchg is not available in this arch.
+ */
+#ifdef CONFIG_SMP
+#define RCUREF_HASH_SIZE       4
+#define RCUREF_HASH(k) \
+       (&__rcuref_hash[(((unsigned long)k)>>8) & (RCUREF_HASH_SIZE-1)])
+#else
+#define        RCUREF_HASH_SIZE        1
+#define RCUREF_HASH(k)         &__rcuref_hash[0]
+#endif                         /* CONFIG_SMP */
+
+/**
+ * rcuref_inc - increment refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference in a lock-free
+ * reader-side critical section.
+ */
+static inline void rcuref_inc(atomic_t *rcuref)
+{
+       unsigned long flags;
+       spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+       rcuref->counter += 1;
+       spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+}
+
+/**
+ * rcuref_dec - decrement refcount for object.
+ * @rcuref: reference counter in the object in question.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference in a lock-free
+ * reader-side critical section.
+ */
+static inline void rcuref_dec(atomic_t *rcuref)
+{
+       unsigned long flags;
+       spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+       rcuref->counter -= 1;
+       spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+}
+
+/**
+ * rcuref_dec_and_test - decrement refcount for object and test
+ * @rcuref: reference counter in the object.
+ * @release: pointer to the function that will clean up the object
+ *          when the last reference to the object is released.
+ *          This pointer is required.
+ *
+ * Decrement the refcount, and if 0, return 1. Else return 0.
+ *
+ * This should be used only for objects where we use RCU and
+ * use the rcuref_inc_lf() api to acquire a reference in a lock-free
+ * reader-side critical section.
+ */
+static inline int rcuref_dec_and_test(atomic_t *rcuref)
+{
+       unsigned long flags;
+       spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+       rcuref->counter--;
+       if (!rcuref->counter) {
+               spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+               return 1;
+       } else {
+               spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+               return 0;
+       }
+}
+
+/**
+ * rcuref_inc_lf - Take reference to an object of a lock-free collection
+ * by traversing a lock-free list/array.
+ * @rcuref: reference counter in the object in question.
+ *
+ * Try and increment the refcount by 1.  The increment might fail if
+ * the reference counter has been through a 1 to 0 transition and
+ * object is no longer part of the lock-free list.
+ * Returns non-zero on successful increment and zero otherwise.
+ */
+static inline int rcuref_inc_lf(atomic_t *rcuref)
+{
+       int ret;
+       unsigned long flags;
+       spin_lock_irqsave(RCUREF_HASH(rcuref), flags);
+       if (rcuref->counter)
+               ret = rcuref->counter++;
+       else
+               ret = 0;
+       spin_unlock_irqrestore(RCUREF_HASH(rcuref), flags);
+       return ret;
+}
+
+
+#endif /* !__HAVE_ARCH_CMPXCHG */
+
+#endif /* __KERNEL__ */
+#endif /* _RCUREF_H_ */
index 17e458e17e2bb08708e623e260609a9653d40996..af00b10294cde3abfc57b09a4d6c6867413575b3 100644 (file)
@@ -2097,7 +2097,7 @@ void reiserfs_free_block(struct reiserfs_transaction_handle *th, struct inode *,
                         b_blocknr_t, int for_unformatted);
 int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t *, int,
                               int);
-extern inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
+static inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
                                             b_blocknr_t * new_blocknrs,
                                             int amount_needed)
 {
@@ -2113,7 +2113,7 @@ extern inline int reiserfs_new_form_blocknrs(struct tree_balance *tb,
                                          0);
 }
 
-extern inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
+static inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
                                            *th, struct inode *inode,
                                            b_blocknr_t * new_blocknrs,
                                            struct path *path, long block)
@@ -2130,7 +2130,7 @@ extern inline int reiserfs_new_unf_blocknrs(struct reiserfs_transaction_handle
 }
 
 #ifdef REISERFS_PREALLOCATE
-extern inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
+static inline int reiserfs_new_unf_blocknrs2(struct reiserfs_transaction_handle
                                             *th, struct inode *inode,
                                             b_blocknr_t * new_blocknrs,
                                             struct path *path, long block)
index ea1b5f32ec5c1952cbf254f4563d7d707a85e155..38c8654aaa96b66d327a09aa2b2cf9effb49674d 100644 (file)
@@ -114,6 +114,7 @@ extern unsigned long nr_iowait(void);
 #define TASK_TRACED            8
 #define EXIT_ZOMBIE            16
 #define EXIT_DEAD              32
+#define TASK_NONINTERACTIVE    64
 
 #define __set_task_state(tsk, state_value)             \
        do { (tsk)->state = (state_value); } while (0)
@@ -202,6 +203,8 @@ extern int in_sched_functions(unsigned long addr);
 
 #define        MAX_SCHEDULE_TIMEOUT    LONG_MAX
 extern signed long FASTCALL(schedule_timeout(signed long timeout));
+extern signed long schedule_timeout_interruptible(signed long timeout);
+extern signed long schedule_timeout_uninterruptible(signed long timeout);
 asmlinkage void schedule(void);
 
 struct namespace;
@@ -604,6 +607,11 @@ extern int groups_search(struct group_info *group_info, gid_t grp);
 #define GROUP_AT(gi, i) \
     ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
 
+#ifdef ARCH_HAS_PREFETCH_SWITCH_STACK
+extern void prefetch_stack(struct task_struct*);
+#else
+static inline void prefetch_stack(struct task_struct *t) { }
+#endif
 
 struct audit_context;          /* See audit.c */
 struct mempolicy;
@@ -895,6 +903,8 @@ extern int task_curr(const task_t *p);
 extern int idle_cpu(int cpu);
 extern int sched_setscheduler(struct task_struct *, int, struct sched_param *);
 extern task_t *idle_task(int cpu);
+extern task_t *curr_task(int cpu);
+extern void set_curr_task(int cpu, task_t *p);
 
 void yield(void);
 
index 7aab6ab7c57febdadfd4d8dedea554594b14baa6..55b02e1c73f418696cdbe49f5080985133934e55 100644 (file)
@@ -250,29 +250,37 @@ struct swap_info_struct;
  *     @inode contains the inode structure.
  *     Deallocate the inode security structure and set @inode->i_security to
  *     NULL. 
+ * @inode_init_security:
+ *     Obtain the security attribute name suffix and value to set on a newly
+ *     created inode and set up the incore security field for the new inode.
+ *     This hook is called by the fs code as part of the inode creation
+ *     transaction and provides for atomic labeling of the inode, unlike
+ *     the post_create/mkdir/... hooks called by the VFS.  The hook function
+ *     is expected to allocate the name and value via kmalloc, with the caller
+ *     being responsible for calling kfree after using them.
+ *     If the security module does not use security attributes or does
+ *     not wish to put a security attribute on this particular inode,
+ *     then it should return -EOPNOTSUPP to skip this processing.
+ *     @inode contains the inode structure of the newly created inode.
+ *     @dir contains the inode structure of the parent directory.
+ *     @name will be set to the allocated name suffix (e.g. selinux).
+ *     @value will be set to the allocated attribute value.
+ *     @len will be set to the length of the value.
+ *     Returns 0 if @name and @value have been successfully set,
+ *             -EOPNOTSUPP if no security attribute is needed, or
+ *             -ENOMEM on memory allocation failure.
  * @inode_create:
  *     Check permission to create a regular file.
  *     @dir contains inode structure of the parent of the new file.
  *     @dentry contains the dentry structure for the file to be created.
  *     @mode contains the file mode of the file to be created.
  *     Return 0 if permission is granted.
- * @inode_post_create:
- *     Set the security attributes on a newly created regular file.  This hook
- *     is called after a file has been successfully created.
- *     @dir contains the inode structure of the parent directory of the new file.
- *     @dentry contains the the dentry structure for the newly created file.
- *     @mode contains the file mode.
  * @inode_link:
  *     Check permission before creating a new hard link to a file.
  *     @old_dentry contains the dentry structure for an existing link to the file.
  *     @dir contains the inode structure of the parent directory of the new link.
  *     @new_dentry contains the dentry structure for the new link.
  *     Return 0 if permission is granted.
- * @inode_post_link:
- *     Set security attributes for a new hard link to a file.
- *     @old_dentry contains the dentry structure for the existing link.
- *     @dir contains the inode structure of the parent directory of the new file.
- *     @new_dentry contains the dentry structure for the new file link.
  * @inode_unlink:
  *     Check the permission to remove a hard link to a file. 
  *     @dir contains the inode structure of parent directory of the file.
@@ -284,13 +292,6 @@ struct swap_info_struct;
  *     @dentry contains the dentry structure of the symbolic link.
  *     @old_name contains the pathname of file.
  *     Return 0 if permission is granted.
- * @inode_post_symlink:
- *     @dir contains the inode structure of the parent directory of the new link.
- *     @dentry contains the dentry structure of new symbolic link.
- *     @old_name contains the pathname of file.
- *     Set security attributes for a newly created symbolic link.  Note that
- *     @dentry->d_inode may be NULL, since the filesystem might not
- *     instantiate the dentry (e.g. NFS).
  * @inode_mkdir:
  *     Check permissions to create a new directory in the existing directory
  *     associated with inode strcture @dir. 
@@ -298,11 +299,6 @@ struct swap_info_struct;
  *     @dentry contains the dentry structure of new directory.
  *     @mode contains the mode of new directory.
  *     Return 0 if permission is granted.
- * @inode_post_mkdir:
- *     Set security attributes on a newly created directory.
- *     @dir contains the inode structure of parent of the directory to be created.
- *     @dentry contains the dentry structure of new directory.
- *     @mode contains the mode of new directory.
  * @inode_rmdir:
  *     Check the permission to remove a directory.
  *     @dir contains the inode structure of parent of the directory to be removed.
@@ -318,13 +314,6 @@ struct swap_info_struct;
  *     @mode contains the mode of the new file.
  *     @dev contains the the device number.
  *     Return 0 if permission is granted.
- * @inode_post_mknod:
- *     Set security attributes on a newly created special file (or socket or
- *     fifo file created via the mknod system call).
- *     @dir contains the inode structure of parent of the new node.
- *     @dentry contains the dentry structure of the new node.
- *     @mode contains the mode of the new node.
- *     @dev contains the the device number.
  * @inode_rename:
  *     Check for permission to rename a file or directory.
  *     @old_dir contains the inode structure for parent of the old link.
@@ -332,12 +321,6 @@ struct swap_info_struct;
  *     @new_dir contains the inode structure for parent of the new link.
  *     @new_dentry contains the dentry structure of the new link.
  *     Return 0 if permission is granted.
- * @inode_post_rename:
- *     Set security attributes on a renamed file or directory.
- *     @old_dir contains the inode structure for parent of the old link.
- *     @old_dentry contains the dentry structure of the old link.
- *     @new_dir contains the inode structure for parent of the new link.
- *     @new_dentry contains the dentry structure of the new link.
  * @inode_readlink:
  *     Check the permission to read the symbolic link.
  *     @dentry contains the dentry structure for the file link.
@@ -1080,34 +1063,21 @@ struct security_operations {
 
        int (*inode_alloc_security) (struct inode *inode);      
        void (*inode_free_security) (struct inode *inode);
+       int (*inode_init_security) (struct inode *inode, struct inode *dir,
+                                   char **name, void **value, size_t *len);
        int (*inode_create) (struct inode *dir,
                             struct dentry *dentry, int mode);
-       void (*inode_post_create) (struct inode *dir,
-                                  struct dentry *dentry, int mode);
        int (*inode_link) (struct dentry *old_dentry,
                           struct inode *dir, struct dentry *new_dentry);
-       void (*inode_post_link) (struct dentry *old_dentry,
-                                struct inode *dir, struct dentry *new_dentry);
        int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
        int (*inode_symlink) (struct inode *dir,
                              struct dentry *dentry, const char *old_name);
-       void (*inode_post_symlink) (struct inode *dir,
-                                   struct dentry *dentry,
-                                   const char *old_name);
        int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
-       void (*inode_post_mkdir) (struct inode *dir, struct dentry *dentry, 
-                           int mode);
        int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
        int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
                            int mode, dev_t dev);
-       void (*inode_post_mknod) (struct inode *dir, struct dentry *dentry,
-                                 int mode, dev_t dev);
        int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
                             struct inode *new_dir, struct dentry *new_dentry);
-       void (*inode_post_rename) (struct inode *old_dir,
-                                  struct dentry *old_dentry,
-                                  struct inode *new_dir,
-                                  struct dentry *new_dentry);
        int (*inode_readlink) (struct dentry *dentry);
        int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
        int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
@@ -1442,6 +1412,17 @@ static inline void security_inode_free (struct inode *inode)
                return;
        security_ops->inode_free_security (inode);
 }
+
+static inline int security_inode_init_security (struct inode *inode,
+                                               struct inode *dir,
+                                               char **name,
+                                               void **value,
+                                               size_t *len)
+{
+       if (unlikely (IS_PRIVATE (inode)))
+               return -EOPNOTSUPP;
+       return security_ops->inode_init_security (inode, dir, name, value, len);
+}
        
 static inline int security_inode_create (struct inode *dir,
                                         struct dentry *dentry,
@@ -1452,15 +1433,6 @@ static inline int security_inode_create (struct inode *dir,
        return security_ops->inode_create (dir, dentry, mode);
 }
 
-static inline void security_inode_post_create (struct inode *dir,
-                                              struct dentry *dentry,
-                                              int mode)
-{
-       if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
-               return;
-       security_ops->inode_post_create (dir, dentry, mode);
-}
-
 static inline int security_inode_link (struct dentry *old_dentry,
                                       struct inode *dir,
                                       struct dentry *new_dentry)
@@ -1470,15 +1442,6 @@ static inline int security_inode_link (struct dentry *old_dentry,
        return security_ops->inode_link (old_dentry, dir, new_dentry);
 }
 
-static inline void security_inode_post_link (struct dentry *old_dentry,
-                                            struct inode *dir,
-                                            struct dentry *new_dentry)
-{
-       if (new_dentry->d_inode && unlikely (IS_PRIVATE (new_dentry->d_inode)))
-               return;
-       security_ops->inode_post_link (old_dentry, dir, new_dentry);
-}
-
 static inline int security_inode_unlink (struct inode *dir,
                                         struct dentry *dentry)
 {
@@ -1496,15 +1459,6 @@ static inline int security_inode_symlink (struct inode *dir,
        return security_ops->inode_symlink (dir, dentry, old_name);
 }
 
-static inline void security_inode_post_symlink (struct inode *dir,
-                                               struct dentry *dentry,
-                                               const char *old_name)
-{
-       if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
-               return;
-       security_ops->inode_post_symlink (dir, dentry, old_name);
-}
-
 static inline int security_inode_mkdir (struct inode *dir,
                                        struct dentry *dentry,
                                        int mode)
@@ -1514,15 +1468,6 @@ static inline int security_inode_mkdir (struct inode *dir,
        return security_ops->inode_mkdir (dir, dentry, mode);
 }
 
-static inline void security_inode_post_mkdir (struct inode *dir,
-                                             struct dentry *dentry,
-                                             int mode)
-{
-       if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
-               return;
-       security_ops->inode_post_mkdir (dir, dentry, mode);
-}
-
 static inline int security_inode_rmdir (struct inode *dir,
                                        struct dentry *dentry)
 {
@@ -1540,15 +1485,6 @@ static inline int security_inode_mknod (struct inode *dir,
        return security_ops->inode_mknod (dir, dentry, mode, dev);
 }
 
-static inline void security_inode_post_mknod (struct inode *dir,
-                                             struct dentry *dentry,
-                                             int mode, dev_t dev)
-{
-       if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
-               return;
-       security_ops->inode_post_mknod (dir, dentry, mode, dev);
-}
-
 static inline int security_inode_rename (struct inode *old_dir,
                                         struct dentry *old_dentry,
                                         struct inode *new_dir,
@@ -1561,18 +1497,6 @@ static inline int security_inode_rename (struct inode *old_dir,
                                           new_dir, new_dentry);
 }
 
-static inline void security_inode_post_rename (struct inode *old_dir,
-                                              struct dentry *old_dentry,
-                                              struct inode *new_dir,
-                                              struct dentry *new_dentry)
-{
-       if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
-           (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
-               return;
-       security_ops->inode_post_rename (old_dir, old_dentry,
-                                               new_dir, new_dentry);
-}
-
 static inline int security_inode_readlink (struct dentry *dentry)
 {
        if (unlikely (IS_PRIVATE (dentry->d_inode)))
@@ -2171,6 +2095,15 @@ static inline int security_inode_alloc (struct inode *inode)
 
 static inline void security_inode_free (struct inode *inode)
 { }
+
+static inline int security_inode_init_security (struct inode *inode,
+                                               struct inode *dir,
+                                               char **name,
+                                               void **value,
+                                               size_t *len)
+{
+       return -EOPNOTSUPP;
+}
        
 static inline int security_inode_create (struct inode *dir,
                                         struct dentry *dentry,
@@ -2179,11 +2112,6 @@ static inline int security_inode_create (struct inode *dir,
        return 0;
 }
 
-static inline void security_inode_post_create (struct inode *dir,
-                                              struct dentry *dentry,
-                                              int mode)
-{ }
-
 static inline int security_inode_link (struct dentry *old_dentry,
                                       struct inode *dir,
                                       struct dentry *new_dentry)
@@ -2191,11 +2119,6 @@ static inline int security_inode_link (struct dentry *old_dentry,
        return 0;
 }
 
-static inline void security_inode_post_link (struct dentry *old_dentry,
-                                            struct inode *dir,
-                                            struct dentry *new_dentry)
-{ }
-
 static inline int security_inode_unlink (struct inode *dir,
                                         struct dentry *dentry)
 {
@@ -2209,11 +2132,6 @@ static inline int security_inode_symlink (struct inode *dir,
        return 0;
 }
 
-static inline void security_inode_post_symlink (struct inode *dir,
-                                               struct dentry *dentry,
-                                               const char *old_name)
-{ }
-
 static inline int security_inode_mkdir (struct inode *dir,
                                        struct dentry *dentry,
                                        int mode)
@@ -2221,11 +2139,6 @@ static inline int security_inode_mkdir (struct inode *dir,
        return 0;
 }
 
-static inline void security_inode_post_mkdir (struct inode *dir,
-                                             struct dentry *dentry,
-                                             int mode)
-{ }
-
 static inline int security_inode_rmdir (struct inode *dir,
                                        struct dentry *dentry)
 {
@@ -2239,11 +2152,6 @@ static inline int security_inode_mknod (struct inode *dir,
        return 0;
 }
 
-static inline void security_inode_post_mknod (struct inode *dir,
-                                             struct dentry *dentry,
-                                             int mode, dev_t dev)
-{ }
-
 static inline int security_inode_rename (struct inode *old_dir,
                                         struct dentry *old_dentry,
                                         struct inode *new_dir,
@@ -2252,12 +2160,6 @@ static inline int security_inode_rename (struct inode *old_dir,
        return 0;
 }
 
-static inline void security_inode_post_rename (struct inode *old_dir,
-                                              struct dentry *old_dentry,
-                                              struct inode *new_dir,
-                                              struct dentry *new_dentry)
-{ }
-
 static inline int security_inode_readlink (struct dentry *dentry)
 {
        return 0;
index 42a6bea58af369f4408eba0cf020dbc6d74352eb..1f356f3bbc6468d56a75abe833eea06280c199aa 100644 (file)
@@ -118,7 +118,8 @@ extern void kfree(const void *);
 extern unsigned int ksize(const void *);
 
 #ifdef CONFIG_NUMA
-extern void *kmem_cache_alloc_node(kmem_cache_t *, int flags, int node);
+extern void *kmem_cache_alloc_node(kmem_cache_t *,
+                       unsigned int __nocast flags, int node);
 extern void *kmalloc_node(size_t size, unsigned int __nocast flags, int node);
 #else
 static inline void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int node)
index d6ba068719b61bf4a035e4d6e297694b65941442..cdc99a27840d6433cabf5d7a6c5bfa6e43198215 100644 (file)
@@ -2,7 +2,48 @@
 #define __LINUX_SPINLOCK_H
 
 /*
- * include/linux/spinlock.h - generic locking declarations
+ * include/linux/spinlock.h - generic spinlock/rwlock declarations
+ *
+ * here's the role of the various spinlock/rwlock related include files:
+ *
+ * on SMP builds:
+ *
+ *  asm/spinlock_types.h: contains the raw_spinlock_t/raw_rwlock_t and the
+ *                        initializers
+ *
+ *  linux/spinlock_types.h:
+ *                        defines the generic type and initializers
+ *
+ *  asm/spinlock.h:       contains the __raw_spin_*()/etc. lowlevel
+ *                        implementations, mostly inline assembly code
+ *
+ *   (also included on UP-debug builds:)
+ *
+ *  linux/spinlock_api_smp.h:
+ *                        contains the prototypes for the _spin_*() APIs.
+ *
+ *  linux/spinlock.h:     builds the final spin_*() APIs.
+ *
+ * on UP builds:
+ *
+ *  linux/spinlock_type_up.h:
+ *                        contains the generic, simplified UP spinlock type.
+ *                        (which is an empty structure on non-debug builds)
+ *
+ *  linux/spinlock_types.h:
+ *                        defines the generic type and initializers
+ *
+ *  linux/spinlock_up.h:
+ *                        contains the __raw_spin_*()/etc. version of UP
+ *                        builds. (which are NOPs on non-debug, non-preempt
+ *                        builds)
+ *
+ *   (included on UP-non-debug builds:)
+ *
+ *  linux/spinlock_api_up.h:
+ *                        builds the _spin_*() APIs.
+ *
+ *  linux/spinlock.h:     builds the final spin_*() APIs.
  */
 
 #include <linux/config.h>
@@ -13,7 +54,6 @@
 #include <linux/kernel.h>
 #include <linux/stringify.h>
 
-#include <asm/processor.h>     /* for cpu relax */
 #include <asm/system.h>
 
 /*
 #define __lockfunc fastcall __attribute__((section(".spinlock.text")))
 
 /*
- * If CONFIG_SMP is set, pull in the _raw_* definitions
+ * Pull the raw_spinlock_t and raw_rwlock_t definitions:
  */
-#ifdef CONFIG_SMP
-
-#define assert_spin_locked(x)  BUG_ON(!spin_is_locked(x))
-#include <asm/spinlock.h>
-
-int __lockfunc _spin_trylock(spinlock_t *lock);
-int __lockfunc _read_trylock(rwlock_t *lock);
-int __lockfunc _write_trylock(rwlock_t *lock);
-
-void __lockfunc _spin_lock(spinlock_t *lock)   __acquires(spinlock_t);
-void __lockfunc _read_lock(rwlock_t *lock)     __acquires(rwlock_t);
-void __lockfunc _write_lock(rwlock_t *lock)    __acquires(rwlock_t);
-
-void __lockfunc _spin_unlock(spinlock_t *lock) __releases(spinlock_t);
-void __lockfunc _read_unlock(rwlock_t *lock)   __releases(rwlock_t);
-void __lockfunc _write_unlock(rwlock_t *lock)  __releases(rwlock_t);
-
-unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)  __acquires(spinlock_t);
-unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)    __acquires(rwlock_t);
-unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)   __acquires(rwlock_t);
-
-void __lockfunc _spin_lock_irq(spinlock_t *lock)       __acquires(spinlock_t);
-void __lockfunc _spin_lock_bh(spinlock_t *lock)                __acquires(spinlock_t);
-void __lockfunc _read_lock_irq(rwlock_t *lock)         __acquires(rwlock_t);
-void __lockfunc _read_lock_bh(rwlock_t *lock)          __acquires(rwlock_t);
-void __lockfunc _write_lock_irq(rwlock_t *lock)                __acquires(rwlock_t);
-void __lockfunc _write_lock_bh(rwlock_t *lock)         __acquires(rwlock_t);
-
-void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) __releases(spinlock_t);
-void __lockfunc _spin_unlock_irq(spinlock_t *lock)                             __releases(spinlock_t);
-void __lockfunc _spin_unlock_bh(spinlock_t *lock)                              __releases(spinlock_t);
-void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)   __releases(rwlock_t);
-void __lockfunc _read_unlock_irq(rwlock_t *lock)                               __releases(rwlock_t);
-void __lockfunc _read_unlock_bh(rwlock_t *lock)                                        __releases(rwlock_t);
-void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  __releases(rwlock_t);
-void __lockfunc _write_unlock_irq(rwlock_t *lock)                              __releases(rwlock_t);
-void __lockfunc _write_unlock_bh(rwlock_t *lock)                               __releases(rwlock_t);
-
-int __lockfunc _spin_trylock_bh(spinlock_t *lock);
-int __lockfunc generic_raw_read_trylock(rwlock_t *lock);
-int in_lock_functions(unsigned long addr);
-
-#else
+#include <linux/spinlock_types.h>
 
-#define in_lock_functions(ADDR) 0
+extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock);
 
-#if !defined(CONFIG_PREEMPT) && !defined(CONFIG_DEBUG_SPINLOCK)
-# define _atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
-# define ATOMIC_DEC_AND_LOCK
-#endif
-
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define SPINLOCK_MAGIC 0x1D244B3C
-typedef struct {
-       unsigned long magic;
-       volatile unsigned long lock;
-       volatile unsigned int babble;
-       const char *module;
-       char *owner;
-       int oline;
-} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { SPINLOCK_MAGIC, 0, 10, __FILE__ , NULL, 0}
-
-#define spin_lock_init(x) \
-       do { \
-               (x)->magic = SPINLOCK_MAGIC; \
-               (x)->lock = 0; \
-               (x)->babble = 5; \
-               (x)->module = __FILE__; \
-               (x)->owner = NULL; \
-               (x)->oline = 0; \
-       } while (0)
-
-#define CHECK_LOCK(x) \
-       do { \
-               if ((x)->magic != SPINLOCK_MAGIC) { \
-                       printk(KERN_ERR "%s:%d: spin_is_locked on uninitialized spinlock %p.\n", \
-                                       __FILE__, __LINE__, (x)); \
-               } \
-       } while(0)
-
-#define _raw_spin_lock(x)              \
-       do { \
-               CHECK_LOCK(x); \
-               if ((x)->lock&&(x)->babble) { \
-                       (x)->babble--; \
-                       printk("%s:%d: spin_lock(%s:%p) already locked by %s/%d\n", \
-                                       __FILE__,__LINE__, (x)->module, \
-                                       (x), (x)->owner, (x)->oline); \
-               } \
-               (x)->lock = 1; \
-               (x)->owner = __FILE__; \
-               (x)->oline = __LINE__; \
-       } while (0)
-
-/* without debugging, spin_is_locked on UP always says
- * FALSE. --> printk if already locked. */
-#define spin_is_locked(x) \
-       ({ \
-               CHECK_LOCK(x); \
-               if ((x)->lock&&(x)->babble) { \
-                       (x)->babble--; \
-                       printk("%s:%d: spin_is_locked(%s:%p) already locked by %s/%d\n", \
-                                       __FILE__,__LINE__, (x)->module, \
-                                       (x), (x)->owner, (x)->oline); \
-               } \
-               0; \
-       })
-
-/* with debugging, assert_spin_locked() on UP does check
- * the lock value properly */
-#define assert_spin_locked(x) \
-       ({ \
-               CHECK_LOCK(x); \
-               BUG_ON(!(x)->lock); \
-       })
-
-/* without debugging, spin_trylock on UP always says
- * TRUE. --> printk if already locked. */
-#define _raw_spin_trylock(x) \
-       ({ \
-               CHECK_LOCK(x); \
-               if ((x)->lock&&(x)->babble) { \
-                       (x)->babble--; \
-                       printk("%s:%d: spin_trylock(%s:%p) already locked by %s/%d\n", \
-                                       __FILE__,__LINE__, (x)->module, \
-                                       (x), (x)->owner, (x)->oline); \
-               } \
-               (x)->lock = 1; \
-               (x)->owner = __FILE__; \
-               (x)->oline = __LINE__; \
-               1; \
-       })
-
-#define spin_unlock_wait(x)    \
-       do { \
-               CHECK_LOCK(x); \
-               if ((x)->lock&&(x)->babble) { \
-                       (x)->babble--; \
-                       printk("%s:%d: spin_unlock_wait(%s:%p) owned by %s/%d\n", \
-                                       __FILE__,__LINE__, (x)->module, (x), \
-                                       (x)->owner, (x)->oline); \
-               }\
-       } while (0)
-
-#define _raw_spin_unlock(x) \
-       do { \
-               CHECK_LOCK(x); \
-               if (!(x)->lock&&(x)->babble) { \
-                       (x)->babble--; \
-                       printk("%s:%d: spin_unlock(%s:%p) not locked\n", \
-                                       __FILE__,__LINE__, (x)->module, (x));\
-               } \
-               (x)->lock = 0; \
-       } while (0)
-#else
 /*
- * gcc versions before ~2.95 have a nasty bug with empty initializers.
+ * Pull the __raw*() functions/declarations (UP-nondebug doesnt need them):
  */
-#if (__GNUC__ > 2)
-  typedef struct { } spinlock_t;
-  #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+#if defined(CONFIG_SMP)
+# include <asm/spinlock.h>
 #else
-  typedef struct { int gcc_is_buggy; } spinlock_t;
-  #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+# include <linux/spinlock_up.h>
 #endif
 
+#define spin_lock_init(lock)   do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0)
+#define rwlock_init(lock)      do { *(lock) = RW_LOCK_UNLOCKED; } while (0)
+
+#define spin_is_locked(lock)   __raw_spin_is_locked(&(lock)->raw_lock)
+
+/**
+ * spin_unlock_wait - wait until the spinlock gets unlocked
+ * @lock: the spinlock in question.
+ */
+#define spin_unlock_wait(lock) __raw_spin_unlock_wait(&(lock)->raw_lock)
+
 /*
- * If CONFIG_SMP is unset, declare the _raw_* definitions as nops
+ * Pull the _spin_*()/_read_*()/_write_*() functions/declarations:
  */
-#define spin_lock_init(lock)   do { (void)(lock); } while(0)
-#define _raw_spin_lock(lock)   do { (void)(lock); } while(0)
-#define spin_is_locked(lock)   ((void)(lock), 0)
-#define assert_spin_locked(lock)       do { (void)(lock); } while(0)
-#define _raw_spin_trylock(lock)        (((void)(lock), 1))
-#define spin_unlock_wait(lock) (void)(lock)
-#define _raw_spin_unlock(lock) do { (void)(lock); } while(0)
-#endif /* CONFIG_DEBUG_SPINLOCK */
-
-/* RW spinlocks: No debug version */
-
-#if (__GNUC__ > 2)
-  typedef struct { } rwlock_t;
-  #define RW_LOCK_UNLOCKED (rwlock_t) { }
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
+# include <linux/spinlock_api_smp.h>
 #else
-  typedef struct { int gcc_is_buggy; } rwlock_t;
-  #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
+# include <linux/spinlock_api_up.h>
 #endif
 
-#define rwlock_init(lock)      do { (void)(lock); } while(0)
-#define _raw_read_lock(lock)   do { (void)(lock); } while(0)
-#define _raw_read_unlock(lock) do { (void)(lock); } while(0)
-#define _raw_write_lock(lock)  do { (void)(lock); } while(0)
-#define _raw_write_unlock(lock)        do { (void)(lock); } while(0)
-#define read_can_lock(lock)    (((void)(lock), 1))
-#define write_can_lock(lock)   (((void)(lock), 1))
-#define _raw_read_trylock(lock) ({ (void)(lock); (1); })
-#define _raw_write_trylock(lock) ({ (void)(lock); (1); })
-
-#define _spin_trylock(lock)    ({preempt_disable(); _raw_spin_trylock(lock) ? \
-                               1 : ({preempt_enable(); 0;});})
-
-#define _read_trylock(lock)    ({preempt_disable();_raw_read_trylock(lock) ? \
-                               1 : ({preempt_enable(); 0;});})
-
-#define _write_trylock(lock)   ({preempt_disable(); _raw_write_trylock(lock) ? \
-                               1 : ({preempt_enable(); 0;});})
-
-#define _spin_trylock_bh(lock) ({preempt_disable(); local_bh_disable(); \
-                               _raw_spin_trylock(lock) ? \
-                               1 : ({preempt_enable_no_resched(); local_bh_enable(); 0;});})
-
-#define _spin_lock(lock)       \
-do { \
-       preempt_disable(); \
-       _raw_spin_lock(lock); \
-       __acquire(lock); \
-} while(0)
-
-#define _write_lock(lock) \
-do { \
-       preempt_disable(); \
-       _raw_write_lock(lock); \
-       __acquire(lock); \
-} while(0)
-#define _read_lock(lock)       \
-do { \
-       preempt_disable(); \
-       _raw_read_lock(lock); \
-       __acquire(lock); \
-} while(0)
-
-#define _spin_unlock(lock) \
-do { \
-       _raw_spin_unlock(lock); \
-       preempt_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _write_unlock(lock) \
-do { \
-       _raw_write_unlock(lock); \
-       preempt_enable(); \
-       __release(lock); \
-} while(0)
-
-#define _read_unlock(lock) \
-do { \
-       _raw_read_unlock(lock); \
-       preempt_enable(); \
-       __release(lock); \
-} while(0)
-
-#define _spin_lock_irqsave(lock, flags) \
-do {   \
-       local_irq_save(flags); \
-       preempt_disable(); \
-       _raw_spin_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _spin_lock_irq(lock) \
-do { \
-       local_irq_disable(); \
-       preempt_disable(); \
-       _raw_spin_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _spin_lock_bh(lock) \
-do { \
-       local_bh_disable(); \
-       preempt_disable(); \
-       _raw_spin_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _read_lock_irqsave(lock, flags) \
-do {   \
-       local_irq_save(flags); \
-       preempt_disable(); \
-       _raw_read_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _read_lock_irq(lock) \
-do { \
-       local_irq_disable(); \
-       preempt_disable(); \
-       _raw_read_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _read_lock_bh(lock) \
-do { \
-       local_bh_disable(); \
-       preempt_disable(); \
-       _raw_read_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _write_lock_irqsave(lock, flags) \
-do {   \
-       local_irq_save(flags); \
-       preempt_disable(); \
-       _raw_write_lock(lock); \
-       __acquire(lock); \
-} while (0)
+#ifdef CONFIG_DEBUG_SPINLOCK
+ extern void _raw_spin_lock(spinlock_t *lock);
+#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+ extern int _raw_spin_trylock(spinlock_t *lock);
+ extern void _raw_spin_unlock(spinlock_t *lock);
+
+ extern void _raw_read_lock(rwlock_t *lock);
+ extern int _raw_read_trylock(rwlock_t *lock);
+ extern void _raw_read_unlock(rwlock_t *lock);
+ extern void _raw_write_lock(rwlock_t *lock);
+ extern int _raw_write_trylock(rwlock_t *lock);
+ extern void _raw_write_unlock(rwlock_t *lock);
+#else
+# define _raw_spin_unlock(lock)                __raw_spin_unlock(&(lock)->raw_lock)
+# define _raw_spin_trylock(lock)       __raw_spin_trylock(&(lock)->raw_lock)
+# define _raw_spin_lock(lock)          __raw_spin_lock(&(lock)->raw_lock)
+# define _raw_spin_lock_flags(lock, flags) \
+               __raw_spin_lock_flags(&(lock)->raw_lock, *(flags))
+# define _raw_read_lock(rwlock)                __raw_read_lock(&(rwlock)->raw_lock)
+# define _raw_write_lock(rwlock)       __raw_write_lock(&(rwlock)->raw_lock)
+# define _raw_read_unlock(rwlock)      __raw_read_unlock(&(rwlock)->raw_lock)
+# define _raw_write_unlock(rwlock)     __raw_write_unlock(&(rwlock)->raw_lock)
+# define _raw_read_trylock(rwlock)     __raw_read_trylock(&(rwlock)->raw_lock)
+# define _raw_write_trylock(rwlock)    __raw_write_trylock(&(rwlock)->raw_lock)
+#endif
 
-#define _write_lock_irq(lock) \
-do { \
-       local_irq_disable(); \
-       preempt_disable(); \
-       _raw_write_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _write_lock_bh(lock) \
-do { \
-       local_bh_disable(); \
-       preempt_disable(); \
-       _raw_write_lock(lock); \
-       __acquire(lock); \
-} while (0)
-
-#define _spin_unlock_irqrestore(lock, flags) \
-do { \
-       _raw_spin_unlock(lock); \
-       local_irq_restore(flags); \
-       preempt_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _spin_unlock_irq(lock) \
-do { \
-       _raw_spin_unlock(lock); \
-       local_irq_enable(); \
-       preempt_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _spin_unlock_bh(lock) \
-do { \
-       _raw_spin_unlock(lock); \
-       preempt_enable_no_resched(); \
-       local_bh_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _write_unlock_bh(lock) \
-do { \
-       _raw_write_unlock(lock); \
-       preempt_enable_no_resched(); \
-       local_bh_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _read_unlock_irqrestore(lock, flags) \
-do { \
-       _raw_read_unlock(lock); \
-       local_irq_restore(flags); \
-       preempt_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _write_unlock_irqrestore(lock, flags) \
-do { \
-       _raw_write_unlock(lock); \
-       local_irq_restore(flags); \
-       preempt_enable(); \
-       __release(lock); \
-} while (0)
-
-#define _read_unlock_irq(lock) \
-do { \
-       _raw_read_unlock(lock); \
-       local_irq_enable();     \
-       preempt_enable();       \
-       __release(lock); \
-} while (0)
-
-#define _read_unlock_bh(lock)  \
-do { \
-       _raw_read_unlock(lock); \
-       preempt_enable_no_resched();    \
-       local_bh_enable();      \
-       __release(lock); \
-} while (0)
-
-#define _write_unlock_irq(lock)        \
-do { \
-       _raw_write_unlock(lock);        \
-       local_irq_enable();     \
-       preempt_enable();       \
-       __release(lock); \
-} while (0)
-
-#endif /* !SMP */
+#define read_can_lock(rwlock)          __raw_read_can_lock(&(rwlock)->raw_lock)
+#define write_can_lock(rwlock)         __raw_write_can_lock(&(rwlock)->raw_lock)
 
 /*
  * Define the various spin_lock and rw_lock methods.  Note we define these
  * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
  * methods are defined as nops in the case they are not required.
  */
-#define spin_trylock(lock)     __cond_lock(_spin_trylock(lock))
-#define read_trylock(lock)     __cond_lock(_read_trylock(lock))
-#define write_trylock(lock)    __cond_lock(_write_trylock(lock))
+#define spin_trylock(lock)             __cond_lock(_spin_trylock(lock))
+#define read_trylock(lock)             __cond_lock(_read_trylock(lock))
+#define write_trylock(lock)            __cond_lock(_write_trylock(lock))
 
-#define spin_lock(lock)                _spin_lock(lock)
-#define write_lock(lock)       _write_lock(lock)
-#define read_lock(lock)                _read_lock(lock)
+#define spin_lock(lock)                        _spin_lock(lock)
+#define write_lock(lock)               _write_lock(lock)
+#define read_lock(lock)                        _read_lock(lock)
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
 #define spin_lock_irqsave(lock, flags) flags = _spin_lock_irqsave(lock)
 #define read_lock_irqsave(lock, flags) flags = _read_lock_irqsave(lock)
 #define write_lock_irqsave(lock, flags)        flags = _write_lock_irqsave(lock)
@@ -470,137 +171,59 @@ do { \
 #define write_lock_irq(lock)           _write_lock_irq(lock)
 #define write_lock_bh(lock)            _write_lock_bh(lock)
 
-#define spin_unlock(lock)      _spin_unlock(lock)
-#define write_unlock(lock)     _write_unlock(lock)
-#define read_unlock(lock)      _read_unlock(lock)
+#define spin_unlock(lock)              _spin_unlock(lock)
+#define write_unlock(lock)             _write_unlock(lock)
+#define read_unlock(lock)              _read_unlock(lock)
 
-#define spin_unlock_irqrestore(lock, flags)    _spin_unlock_irqrestore(lock, flags)
+#define spin_unlock_irqrestore(lock, flags) \
+                                       _spin_unlock_irqrestore(lock, flags)
 #define spin_unlock_irq(lock)          _spin_unlock_irq(lock)
 #define spin_unlock_bh(lock)           _spin_unlock_bh(lock)
 
-#define read_unlock_irqrestore(lock, flags)    _read_unlock_irqrestore(lock, flags)
-#define read_unlock_irq(lock)                  _read_unlock_irq(lock)
-#define read_unlock_bh(lock)                   _read_unlock_bh(lock)
+#define read_unlock_irqrestore(lock, flags) \
+                                       _read_unlock_irqrestore(lock, flags)
+#define read_unlock_irq(lock)          _read_unlock_irq(lock)
+#define read_unlock_bh(lock)           _read_unlock_bh(lock)
 
-#define write_unlock_irqrestore(lock, flags)   _write_unlock_irqrestore(lock, flags)
-#define write_unlock_irq(lock)                 _write_unlock_irq(lock)
-#define write_unlock_bh(lock)                  _write_unlock_bh(lock)
+#define write_unlock_irqrestore(lock, flags) \
+                                       _write_unlock_irqrestore(lock, flags)
+#define write_unlock_irq(lock)         _write_unlock_irq(lock)
+#define write_unlock_bh(lock)          _write_unlock_bh(lock)
 
-#define spin_trylock_bh(lock)                  __cond_lock(_spin_trylock_bh(lock))
+#define spin_trylock_bh(lock)          __cond_lock(_spin_trylock_bh(lock))
 
 #define spin_trylock_irq(lock) \
 ({ \
        local_irq_disable(); \
        _spin_trylock(lock) ? \
-       1 : ({local_irq_enable(); 0; }); \
+       1 : ({ local_irq_enable(); 0;  }); \
 })
 
 #define spin_trylock_irqsave(lock, flags) \
 ({ \
        local_irq_save(flags); \
        _spin_trylock(lock) ? \
-       1 : ({local_irq_restore(flags); 0;}); \
+       1 : ({ local_irq_restore(flags); 0; }); \
 })
 
-#ifdef CONFIG_LOCKMETER
-extern void _metered_spin_lock   (spinlock_t *lock);
-extern void _metered_spin_unlock (spinlock_t *lock);
-extern int  _metered_spin_trylock(spinlock_t *lock);
-extern void _metered_read_lock    (rwlock_t *lock);
-extern void _metered_read_unlock  (rwlock_t *lock);
-extern void _metered_write_lock   (rwlock_t *lock);
-extern void _metered_write_unlock (rwlock_t *lock);
-extern int  _metered_read_trylock (rwlock_t *lock);
-extern int  _metered_write_trylock(rwlock_t *lock);
-#endif
-
-/* "lock on reference count zero" */
-#ifndef ATOMIC_DEC_AND_LOCK
-#include <asm/atomic.h>
-extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
-#endif
-
-#define atomic_dec_and_lock(atomic,lock) __cond_lock(_atomic_dec_and_lock(atomic,lock))
-
-/*
- *  bit-based spin_lock()
- *
- * Don't use this unless you really need to: spin_lock() and spin_unlock()
- * are significantly faster.
- */
-static inline void bit_spin_lock(int bitnum, unsigned long *addr)
-{
-       /*
-        * Assuming the lock is uncontended, this never enters
-        * the body of the outer loop. If it is contended, then
-        * within the inner loop a non-atomic test is used to
-        * busywait with less bus contention for a good time to
-        * attempt to acquire the lock bit.
-        */
-       preempt_disable();
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-       while (test_and_set_bit(bitnum, addr)) {
-               while (test_bit(bitnum, addr)) {
-                       preempt_enable();
-                       cpu_relax();
-                       preempt_disable();
-               }
-       }
-#endif
-       __acquire(bitlock);
-}
-
 /*
- * Return true if it was acquired
+ * Pull the atomic_t declaration:
+ * (asm-mips/atomic.h needs above definitions)
  */
-static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
-{
-       preempt_disable();      
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-       if (test_and_set_bit(bitnum, addr)) {
-               preempt_enable();
-               return 0;
-       }
-#endif
-       __acquire(bitlock);
-       return 1;
-}
-
-/*
- *  bit-based spin_unlock()
- */
-static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-       BUG_ON(!test_bit(bitnum, addr));
-       smp_mb__before_clear_bit();
-       clear_bit(bitnum, addr);
-#endif
-       preempt_enable();
-       __release(bitlock);
-}
-
-/*
- * Return true if the lock is held.
+#include <asm/atomic.h>
+/**
+ * atomic_dec_and_lock - lock on reaching reference count zero
+ * @atomic: the atomic counter
+ * @lock: the spinlock in question
  */
-static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-       return test_bit(bitnum, addr);
-#elif defined CONFIG_PREEMPT
-       return preempt_count();
-#else
-       return 1;
-#endif
-}
-
-#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
-#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
+extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
+#define atomic_dec_and_lock(atomic, lock) \
+               __cond_lock(_atomic_dec_and_lock(atomic, lock))
 
 /**
  * spin_can_lock - would spin_trylock() succeed?
  * @lock: the spinlock in question.
  */
-#define spin_can_lock(lock)            (!spin_is_locked(lock))
+#define spin_can_lock(lock)    (!spin_is_locked(lock))
 
 #endif /* __LINUX_SPINLOCK_H */
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
new file mode 100644 (file)
index 0000000..78e6989
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __LINUX_SPINLOCK_API_SMP_H
+#define __LINUX_SPINLOCK_API_SMP_H
+
+#ifndef __LINUX_SPINLOCK_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_api_smp.h
+ *
+ * spinlock API declarations on SMP (and debug)
+ * (implemented in kernel/spinlock.c)
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+int in_lock_functions(unsigned long addr);
+
+#define assert_spin_locked(x)  BUG_ON(!spin_is_locked(x))
+
+void __lockfunc _spin_lock(spinlock_t *lock)           __acquires(spinlock_t);
+void __lockfunc _read_lock(rwlock_t *lock)             __acquires(rwlock_t);
+void __lockfunc _write_lock(rwlock_t *lock)            __acquires(rwlock_t);
+void __lockfunc _spin_lock_bh(spinlock_t *lock)                __acquires(spinlock_t);
+void __lockfunc _read_lock_bh(rwlock_t *lock)          __acquires(rwlock_t);
+void __lockfunc _write_lock_bh(rwlock_t *lock)         __acquires(rwlock_t);
+void __lockfunc _spin_lock_irq(spinlock_t *lock)       __acquires(spinlock_t);
+void __lockfunc _read_lock_irq(rwlock_t *lock)         __acquires(rwlock_t);
+void __lockfunc _write_lock_irq(rwlock_t *lock)                __acquires(rwlock_t);
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
+                                                       __acquires(spinlock_t);
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)
+                                                       __acquires(rwlock_t);
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)
+                                                       __acquires(rwlock_t);
+int __lockfunc _spin_trylock(spinlock_t *lock);
+int __lockfunc _read_trylock(rwlock_t *lock);
+int __lockfunc _write_trylock(rwlock_t *lock);
+int __lockfunc _spin_trylock_bh(spinlock_t *lock);
+void __lockfunc _spin_unlock(spinlock_t *lock)         __releases(spinlock_t);
+void __lockfunc _read_unlock(rwlock_t *lock)           __releases(rwlock_t);
+void __lockfunc _write_unlock(rwlock_t *lock)          __releases(rwlock_t);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock)      __releases(spinlock_t);
+void __lockfunc _read_unlock_bh(rwlock_t *lock)                __releases(rwlock_t);
+void __lockfunc _write_unlock_bh(rwlock_t *lock)       __releases(rwlock_t);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock)     __releases(spinlock_t);
+void __lockfunc _read_unlock_irq(rwlock_t *lock)       __releases(rwlock_t);
+void __lockfunc _write_unlock_irq(rwlock_t *lock)      __releases(rwlock_t);
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+                                                       __releases(spinlock_t);
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+                                                       __releases(rwlock_t);
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
+                                                       __releases(rwlock_t);
+
+#endif /* __LINUX_SPINLOCK_API_SMP_H */
diff --git a/include/linux/spinlock_api_up.h b/include/linux/spinlock_api_up.h
new file mode 100644 (file)
index 0000000..cd81cee
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __LINUX_SPINLOCK_API_UP_H
+#define __LINUX_SPINLOCK_API_UP_H
+
+#ifndef __LINUX_SPINLOCK_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_api_up.h
+ *
+ * spinlock API implementation on UP-nondebug (inlined implementation)
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+#define in_lock_functions(ADDR)                0
+
+#define assert_spin_locked(lock)       do { (void)(lock); } while (0)
+
+/*
+ * In the UP-nondebug case there's no real locking going on, so the
+ * only thing we have to do is to keep the preempt counts and irq
+ * flags straight, to supress compiler warnings of unused lock
+ * variables, and to add the proper checker annotations:
+ */
+#define __LOCK(lock) \
+  do { preempt_disable(); __acquire(lock); (void)(lock); } while (0)
+
+#define __LOCK_BH(lock) \
+  do { local_bh_disable(); __LOCK(lock); } while (0)
+
+#define __LOCK_IRQ(lock) \
+  do { local_irq_disable(); __LOCK(lock); } while (0)
+
+#define __LOCK_IRQSAVE(lock, flags) \
+  do { local_irq_save(flags); __LOCK(lock); } while (0)
+
+#define __UNLOCK(lock) \
+  do { preempt_enable(); __release(lock); (void)(lock); } while (0)
+
+#define __UNLOCK_BH(lock) \
+  do { preempt_enable_no_resched(); local_bh_enable(); __release(lock); (void)(lock); } while (0)
+
+#define __UNLOCK_IRQ(lock) \
+  do { local_irq_enable(); __UNLOCK(lock); } while (0)
+
+#define __UNLOCK_IRQRESTORE(lock, flags) \
+  do { local_irq_restore(flags); __UNLOCK(lock); } while (0)
+
+#define _spin_lock(lock)                       __LOCK(lock)
+#define _read_lock(lock)                       __LOCK(lock)
+#define _write_lock(lock)                      __LOCK(lock)
+#define _spin_lock_bh(lock)                    __LOCK_BH(lock)
+#define _read_lock_bh(lock)                    __LOCK_BH(lock)
+#define _write_lock_bh(lock)                   __LOCK_BH(lock)
+#define _spin_lock_irq(lock)                   __LOCK_IRQ(lock)
+#define _read_lock_irq(lock)                   __LOCK_IRQ(lock)
+#define _write_lock_irq(lock)                  __LOCK_IRQ(lock)
+#define _spin_lock_irqsave(lock, flags)                __LOCK_IRQSAVE(lock, flags)
+#define _read_lock_irqsave(lock, flags)                __LOCK_IRQSAVE(lock, flags)
+#define _write_lock_irqsave(lock, flags)       __LOCK_IRQSAVE(lock, flags)
+#define _spin_trylock(lock)                    ({ __LOCK(lock); 1; })
+#define _read_trylock(lock)                    ({ __LOCK(lock); 1; })
+#define _write_trylock(lock)                   ({ __LOCK(lock); 1; })
+#define _spin_trylock_bh(lock)                 ({ __LOCK_BH(lock); 1; })
+#define _spin_unlock(lock)                     __UNLOCK(lock)
+#define _read_unlock(lock)                     __UNLOCK(lock)
+#define _write_unlock(lock)                    __UNLOCK(lock)
+#define _spin_unlock_bh(lock)                  __UNLOCK_BH(lock)
+#define _write_unlock_bh(lock)                 __UNLOCK_BH(lock)
+#define _read_unlock_bh(lock)                  __UNLOCK_BH(lock)
+#define _spin_unlock_irq(lock)                 __UNLOCK_IRQ(lock)
+#define _read_unlock_irq(lock)                 __UNLOCK_IRQ(lock)
+#define _write_unlock_irq(lock)                        __UNLOCK_IRQ(lock)
+#define _spin_unlock_irqrestore(lock, flags)   __UNLOCK_IRQRESTORE(lock, flags)
+#define _read_unlock_irqrestore(lock, flags)   __UNLOCK_IRQRESTORE(lock, flags)
+#define _write_unlock_irqrestore(lock, flags)  __UNLOCK_IRQRESTORE(lock, flags)
+
+#endif /* __LINUX_SPINLOCK_API_UP_H */
diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h
new file mode 100644 (file)
index 0000000..9cb51e0
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __LINUX_SPINLOCK_TYPES_H
+#define __LINUX_SPINLOCK_TYPES_H
+
+/*
+ * include/linux/spinlock_types.h - generic spinlock type definitions
+ *                                  and initializers
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+#if defined(CONFIG_SMP)
+# include <asm/spinlock_types.h>
+#else
+# include <linux/spinlock_types_up.h>
+#endif
+
+typedef struct {
+       raw_spinlock_t raw_lock;
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
+       unsigned int break_lock;
+#endif
+#ifdef CONFIG_DEBUG_SPINLOCK
+       unsigned int magic, owner_cpu;
+       void *owner;
+#endif
+} spinlock_t;
+
+#define SPINLOCK_MAGIC         0xdead4ead
+
+typedef struct {
+       raw_rwlock_t raw_lock;
+#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
+       unsigned int break_lock;
+#endif
+#ifdef CONFIG_DEBUG_SPINLOCK
+       unsigned int magic, owner_cpu;
+       void *owner;
+#endif
+} rwlock_t;
+
+#define RWLOCK_MAGIC           0xdeaf1eed
+
+#define SPINLOCK_OWNER_INIT    ((void *)-1L)
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+# define SPIN_LOCK_UNLOCKED                                            \
+       (spinlock_t)    {       .raw_lock = __RAW_SPIN_LOCK_UNLOCKED,   \
+                               .magic = SPINLOCK_MAGIC,                \
+                               .owner = SPINLOCK_OWNER_INIT,           \
+                               .owner_cpu = -1 }
+#define RW_LOCK_UNLOCKED                                               \
+       (rwlock_t)      {       .raw_lock = __RAW_RW_LOCK_UNLOCKED,     \
+                               .magic = RWLOCK_MAGIC,                  \
+                               .owner = SPINLOCK_OWNER_INIT,           \
+                               .owner_cpu = -1 }
+#else
+# define SPIN_LOCK_UNLOCKED \
+       (spinlock_t)    {       .raw_lock = __RAW_SPIN_LOCK_UNLOCKED }
+#define RW_LOCK_UNLOCKED \
+       (rwlock_t)      {       .raw_lock = __RAW_RW_LOCK_UNLOCKED }
+#endif
+
+#define DEFINE_SPINLOCK(x)     spinlock_t x = SPIN_LOCK_UNLOCKED
+#define DEFINE_RWLOCK(x)       rwlock_t x = RW_LOCK_UNLOCKED
+
+#endif /* __LINUX_SPINLOCK_TYPES_H */
diff --git a/include/linux/spinlock_types_up.h b/include/linux/spinlock_types_up.h
new file mode 100644 (file)
index 0000000..def2d17
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __LINUX_SPINLOCK_TYPES_UP_H
+#define __LINUX_SPINLOCK_TYPES_UP_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_types_up.h - spinlock type definitions for UP
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ */
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+typedef struct {
+       volatile unsigned int slock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+
+#else
+
+/*
+ * All gcc 2.95 versions and early versions of 2.96 have a nasty bug
+ * with empty initializers.
+ */
+#if (__GNUC__ > 2)
+typedef struct { } raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { }
+#else
+typedef struct { int gcc_is_buggy; } raw_spinlock_t;
+#define __RAW_SPIN_LOCK_UNLOCKED (raw_spinlock_t) { 0 }
+#endif
+
+#endif
+
+#if (__GNUC__ > 2)
+typedef struct {
+       /* no debug version on UP */
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { }
+#else
+typedef struct { int gcc_is_buggy; } raw_rwlock_t;
+#define __RAW_RW_LOCK_UNLOCKED (raw_rwlock_t) { 0 }
+#endif
+
+#endif /* __LINUX_SPINLOCK_TYPES_UP_H */
diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h
new file mode 100644 (file)
index 0000000..31accf2
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __LINUX_SPINLOCK_UP_H
+#define __LINUX_SPINLOCK_UP_H
+
+#ifndef __LINUX_SPINLOCK_H
+# error "please don't include this file directly"
+#endif
+
+/*
+ * include/linux/spinlock_up.h - UP-debug version of spinlocks.
+ *
+ * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ *
+ * In the debug case, 1 means unlocked, 0 means locked. (the values
+ * are inverted, to catch initialization bugs)
+ *
+ * No atomicity anywhere, we are on UP.
+ */
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+
+#define __raw_spin_is_locked(x)                ((x)->slock == 0)
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+       lock->slock = 0;
+}
+
+static inline void
+__raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
+{
+       local_irq_save(flags);
+       lock->slock = 0;
+}
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+       char oldval = lock->slock;
+
+       lock->slock = 0;
+
+       return oldval > 0;
+}
+
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+       lock->slock = 1;
+}
+
+/*
+ * Read-write spinlocks. No debug version.
+ */
+#define __raw_read_lock(lock)          do { (void)(lock); } while (0)
+#define __raw_write_lock(lock)         do { (void)(lock); } while (0)
+#define __raw_read_trylock(lock)       ({ (void)(lock); 1; })
+#define __raw_write_trylock(lock)      ({ (void)(lock); 1; })
+#define __raw_read_unlock(lock)                do { (void)(lock); } while (0)
+#define __raw_write_unlock(lock)       do { (void)(lock); } while (0)
+
+#else /* DEBUG_SPINLOCK */
+#define __raw_spin_is_locked(lock)     ((void)(lock), 0)
+/* for sched.c and kernel_lock.c: */
+# define __raw_spin_lock(lock)         do { (void)(lock); } while (0)
+# define __raw_spin_unlock(lock)       do { (void)(lock); } while (0)
+# define __raw_spin_trylock(lock)      ({ (void)(lock); 1; })
+#endif /* DEBUG_SPINLOCK */
+
+#define __raw_read_can_lock(lock)      (((void)(lock), 1))
+#define __raw_write_can_lock(lock)     (((void)(lock), 1))
+
+#define __raw_spin_unlock_wait(lock) \
+               do { cpu_relax(); } while (__raw_spin_is_locked(lock))
+
+#endif /* __LINUX_SPINLOCK_UP_H */
index c10d4c21c18397cd3bfe66ea83d173d89a5d85b2..8e83f4e778bb11657f2363cf82eb491562615439 100644 (file)
@@ -28,17 +28,10 @@ struct timezone {
 #ifdef __KERNEL__
 
 /* Parameters used to convert the timespec values */
-#ifndef USEC_PER_SEC
+#define MSEC_PER_SEC (1000L)
 #define USEC_PER_SEC (1000000L)
-#endif
-
-#ifndef NSEC_PER_SEC
 #define NSEC_PER_SEC (1000000000L)
-#endif
-
-#ifndef NSEC_PER_USEC
 #define NSEC_PER_USEC (1000L)
-#endif
 
 static __inline__ int timespec_equal(struct timespec *a, struct timespec *b) 
 { 
index 221f81ac2002b29a454855b918fd106f069413ad..3340f3bd135daa9c4c42741d98df1a6b469e6ba6 100644 (file)
@@ -32,6 +32,10 @@ extern struct timer_base_s __init_timer_base;
                .magic = TIMER_MAGIC,                           \
        }
 
+#define DEFINE_TIMER(_name, _function, _expires, _data)                \
+       struct timer_list _name =                               \
+               TIMER_INITIALIZER(_function, _expires, _data)
+
 void fastcall init_timer(struct timer_list * timer);
 
 /***
index 59ff42c629ece02d39f81b12959e164a5918965e..1267f88ece6eae9616453c1128859cbf49754000 100644 (file)
@@ -74,7 +74,8 @@ struct screen_info {
        u16 vesapm_off;         /* 0x30 */
        u16 pages;              /* 0x32 */
        u16 vesa_attributes;    /* 0x34 */
-                               /* 0x36 -- 0x3f reserved for future expansion */
+       u32  capabilities;      /* 0x36 */
+                               /* 0x3a -- 0x3f reserved for future expansion */
 };
 
 extern struct screen_info screen_info;
index 9d6fbde3d29cf3a8eddc1035e79ec6a6c2532241..1cc8c31b798878aea1469b989e74e6fda2d65237 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/version.h>
 
 #define HAVE_V4L2 1
 #include <linux/videodev2.h>
@@ -29,7 +28,6 @@ struct video_device
        void (*release)(struct video_device *vfd);
 
 
-#if 1 /* to be removed in 2.7.x */
        /* obsolete -- fops->owner is used instead */
        struct module *owner;
        /* dev->driver_data will be used instead some day.
@@ -37,7 +35,6 @@ struct video_device
         * so the switch over will be transparent for you.
         * Or use {pci|usb}_{get|set}_drvdata() directly. */
        void *priv;
-#endif
 
        /* for videodev.c intenal usage -- please don't touch */
        int users;                     /* video_exclusive_{open|close} ... */
index acbfc525576df3eb2cb7803bf866e38a2d2ea2bb..f623a33b9abe856ea37a01be04ac515727498ae2 100644 (file)
@@ -270,7 +270,6 @@ struct v4l2_timecode
 /* The above is based on SMPTE timecodes */
 
 
-#if 1
 /*
  *     M P E G   C O M P R E S S I O N   P A R A M E T E R S
  *
@@ -357,7 +356,6 @@ struct v4l2_mpeg_compression {
        /* I don't expect the above being perfect yet ;) */
        __u32                           reserved_5[8];
 };
-#endif
 
 struct v4l2_jpegcompression
 {
@@ -871,10 +869,8 @@ struct v4l2_streamparm
 #define VIDIOC_ENUM_FMT         _IOWR ('V',  2, struct v4l2_fmtdesc)
 #define VIDIOC_G_FMT           _IOWR ('V',  4, struct v4l2_format)
 #define VIDIOC_S_FMT           _IOWR ('V',  5, struct v4l2_format)
-#if 1 /* experimental */
 #define VIDIOC_G_MPEGCOMP       _IOR  ('V',  6, struct v4l2_mpeg_compression)
 #define VIDIOC_S_MPEGCOMP      _IOW  ('V',  7, struct v4l2_mpeg_compression)
-#endif
 #define VIDIOC_REQBUFS         _IOWR ('V',  8, struct v4l2_requestbuffers)
 #define VIDIOC_QUERYBUF                _IOWR ('V',  9, struct v4l2_buffer)
 #define VIDIOC_G_FBUF          _IOR  ('V', 10, struct v4l2_framebuffer)
index 542dbaee65129480867593be885ab71c05be8796..343d883d69c5d56314b7b15280513376f1b6d1bd 100644 (file)
@@ -109,8 +109,6 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
 int sync_page_range(struct inode *inode, struct address_space *mapping,
                        loff_t pos, size_t count);
-int sync_page_range_nolock(struct inode *inode, struct address_space
-               *mapping, loff_t pos, size_t count);
 
 /* pdflush.c */
 extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
index cd831168fdc1df41767cc6b2dd005b5b01fa49a1..a7ceee9fc5e9a0edd113a2c9c2ecdd52c8a50425 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: audiochip.h,v 1.5 2005/06/16 22:59:16 hhackmann Exp $
  */
 
 #ifndef AUDIOCHIP_H
index 801ddef301aa374e16008b29ab139f165fd3def3..6d02c94cdc0db4dcb5b888ec95e2fe5f4f4beeae 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: id.h,v 1.4 2005/06/12 04:19:19 mchehab Exp $
  */
 
 /* FIXME: this temporarely, until these are included in linux/i2c-id.h */
index 698670547f1684679a28c0fbc601cdeefc9f6c33..01b56822df4d9a9077aa3adaf6c5d9b714ee39ff 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: ir-common.h,v 1.9 2005/05/15 19:01:26 mchehab Exp $
  *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/version.h>
 #include <linux/input.h>
 
 
 #define IR_TYPE_RC5     1
+#define IR_TYPE_PD      2 /* Pulse distance encoded IR */
 #define IR_TYPE_OTHER  99
 
 #define IR_KEYTAB_TYPE u32
@@ -60,6 +59,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
 u32  ir_extract_bits(u32 data, u32 mask);
 int  ir_dump_samples(u32 *samples, int count);
 int  ir_decode_biphase(u32 *samples, int count, int low, int high);
+int  ir_decode_pulsedistance(u32 *samples, int count, int low, int high);
 
 /*
  * Local variables:
index 3dfb8d670eb789a294789839fc0fa00ef8c7fba9..2a897c3a6a9af9fd2a483843f452ddb01ac91cdd 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __SAA7146__
 #define __SAA7146__
 
-#include <linux/version.h>     /* for version macros */
 #include <linux/module.h>      /* for module-version */
 #include <linux/delay.h>       /* for delay-stuff */
 #include <linux/slab.h>                /* for kmalloc/kfree */
 #include <linux/vmalloc.h>     /* for vmalloc() */
 #include <linux/mm.h>          /* for vmalloc_to_page() */
 
-/* ugly, but necessary to build the dvb stuff under 2.4. */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
-       #include "dvb_functions.h"
-#endif
-
-#define SAA7146_VERSION_CODE KERNEL_VERSION(0,5,0)
+#define SAA7146_VERSION_CODE 0x000500   /* 0.5.0 */
 
 #define saa7146_write(sxy,adr,dat)    writel((dat),(sxy->mem+(adr)))
 #define saa7146_read(sxy,adr)         readl(sxy->mem+(adr))
@@ -33,13 +27,8 @@ extern unsigned int saa7146_debug;
        #define DEBUG_VARIABLE saa7146_debug
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
-#define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_BASENAME),__FUNCTION__)
-#define INFO(x) { printk("%s: ",__stringify(KBUILD_BASENAME)); printk x; }
-#else
 #define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_MODNAME),__FUNCTION__)
 #define INFO(x) { printk("%s: ",__stringify(KBUILD_MODNAME)); printk x; }
-#endif
 
 #define ERR(x) { DEBUG_PROLOG; printk x; }
 
index eeaa15ddee8512e303671b1fd40e33f04be101f0..4ad08e24a1aa2cc32933a5092f66dfb011a7b020 100644 (file)
@@ -1,6 +1,4 @@
-
-/* $Id: tuner.h,v 1.45 2005/07/28 18:41:21 mchehab Exp $
- *
+/*
     tuner.h - definition for different tuners
 
     Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
 
 #define ADDR_UNSET (255)
 
-#define TUNER_TEMIC_PAL     0        /* 4002 FH5 (3X 7756, 9483) */
-#define TUNER_PHILIPS_PAL_I 1
-#define TUNER_PHILIPS_NTSC  2
-#define TUNER_PHILIPS_SECAM 3          /* you must actively select B/G, L, L` */
-
-#define TUNER_ABSENT        4
-#define TUNER_PHILIPS_PAL   5
-#define TUNER_TEMIC_NTSC           /* 4032 FY5 (3X 7004, 9498, 9789)  */
-#define TUNER_TEMIC_PAL_I   7        /* 4062 FY5 (3X 8501, 9957)        */
-
-#define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5 (3X 1223, 1981, 7686)  */
-#define TUNER_ALPS_TSBH1_NTSC   9
-#define TUNER_ALPS_TSBE1_PAL   10
-#define TUNER_ALPS_TSBB5_PAL_I         11
-
-#define TUNER_ALPS_TSBE5_PAL   12
-#define TUNER_ALPS_TSBC5_PAL   13
-#define TUNER_TEMIC_4006FH5_PAL        14   /* 4006 FH5 (3X 9500, 9501, 7291)     */
-#define TUNER_ALPS_TSHC6_NTSC  15
-
-#define TUNER_TEMIC_PAL_DK     16   /* 4016 FY5 (3X 1392, 1393)     */
-#define TUNER_PHILIPS_NTSC_M   17
-#define TUNER_TEMIC_4066FY5_PAL_I       18  /* 4066 FY5 (3X 7032, 7035) */
-#define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
-
-#define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio (3X 7607, 7488, 7711)*/
-#define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio (3X 7246, 7578, 7732)*/
-#define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  (3X 7804, 7806, 8103, 8104)*/
+#define TUNER_TEMIC_PAL                        0        /* 4002 FH5 (3X 7756, 9483) */
+#define TUNER_PHILIPS_PAL_I            1
+#define TUNER_PHILIPS_NTSC             2
+#define TUNER_PHILIPS_SECAM            3       /* you must actively select B/G, L, L` */
+
+#define TUNER_ABSENT                   4
+#define TUNER_PHILIPS_PAL              5
+#define TUNER_TEMIC_NTSC               6       /* 4032 FY5 (3X 7004, 9498, 9789)  */
+#define TUNER_TEMIC_PAL_I              7       /* 4062 FY5 (3X 8501, 9957) */
+
+#define TUNER_TEMIC_4036FY5_NTSC       8       /* 4036 FY5 (3X 1223, 1981, 7686) */
+#define TUNER_ALPS_TSBH1_NTSC          9
+#define TUNER_ALPS_TSBE1_PAL           10
+#define TUNER_ALPS_TSBB5_PAL_I         11
+
+#define TUNER_ALPS_TSBE5_PAL           12
+#define TUNER_ALPS_TSBC5_PAL           13
+#define TUNER_TEMIC_4006FH5_PAL                14      /* 4006 FH5 (3X 9500, 9501, 7291) */
+#define TUNER_ALPS_TSHC6_NTSC          15
+
+#define TUNER_TEMIC_PAL_DK             16      /* 4016 FY5 (3X 1392, 1393) */
+#define TUNER_PHILIPS_NTSC_M           17
+#define TUNER_TEMIC_4066FY5_PAL_I      18      /* 4066 FY5 (3X 7032, 7035) */
+#define TUNER_TEMIC_4006FN5_MULTI_PAL  19      /* B/G, I and D/K autodetected (3X 7595, 7606, 7657) */
+
+#define TUNER_TEMIC_4009FR5_PAL                20      /* incl. FM radio (3X 7607, 7488, 7711) */
+#define TUNER_TEMIC_4039FR5_NTSC       21      /* incl. FM radio (3X 7246, 7578, 7732) */
+#define TUNER_TEMIC_4046FM5            22      /* you must actively select B/G, D/K, I, L, L` !  (3X 7804, 7806, 8103, 8104) */
 #define TUNER_PHILIPS_PAL_DK           23
 
-#define TUNER_PHILIPS_FQ1216ME         24  /* you must actively select B/G/D/K, I, L, L` */
-#define TUNER_LG_PAL_I_FM      25
-#define TUNER_LG_PAL_I         26
-#define TUNER_LG_NTSC_FM       27
+#define TUNER_PHILIPS_FQ1216ME         24      /* you must actively select B/G/D/K, I, L, L` */
+#define TUNER_LG_PAL_I_FM              25
+#define TUNER_LG_PAL_I                 26
+#define TUNER_LG_NTSC_FM               27
 
-#define TUNER_LG_PAL_FM                28
-#define TUNER_LG_PAL           29
-#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM       30  /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
-#define TUNER_SHARP_2U5JF5540_NTSC  31
+#define TUNER_LG_PAL_FM                        28
+#define TUNER_LG_PAL                   29
+#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30    /* B/G, I and D/K autodetected (3X 8155, 8160, 8163) */
+#define TUNER_SHARP_2U5JF5540_NTSC     31
 
-#define TUNER_Samsung_PAL_TCPM9091PD27 32
-#define TUNER_MT2032 33
-#define TUNER_TEMIC_4106FH5    34      /* 4106 FH5 (3X 7808, 7865)*/
-#define TUNER_TEMIC_4012FY5    35      /* 4012 FY5 (3X 0971, 1099)*/
+#define TUNER_Samsung_PAL_TCPM9091PD27 32
+#define TUNER_MT2032                   33
+#define TUNER_TEMIC_4106FH5            34      /* 4106 FH5 (3X 7808, 7865) */
+#define TUNER_TEMIC_4012FY5            35      /* 4012 FY5 (3X 0971, 1099) */
 
-#define TUNER_TEMIC_4136FY5    36      /* 4136 FY5 (3X 7708, 7746)*/
-#define TUNER_LG_PAL_NEW_TAPC   37
-#define TUNER_PHILIPS_FM1216ME_MK3  38
-#define TUNER_LG_NTSC_NEW_TAPC   39
+#define TUNER_TEMIC_4136FY5            36      /* 4136 FY5 (3X 7708, 7746) */
+#define TUNER_LG_PAL_NEW_TAPC          37
+#define TUNER_PHILIPS_FM1216ME_MK3     38
+#define TUNER_LG_NTSC_NEW_TAPC         39
 
-#define TUNER_HITACHI_NTSC       40
-#define TUNER_PHILIPS_PAL_MK     41
-#define TUNER_PHILIPS_ATSC       42
-#define TUNER_PHILIPS_FM1236_MK3 43
+#define TUNER_HITACHI_NTSC             40
+#define TUNER_PHILIPS_PAL_MK           41
+#define TUNER_PHILIPS_ATSC             42
+#define TUNER_PHILIPS_FM1236_MK3       43
 
-#define TUNER_PHILIPS_4IN1       44    /* ATI TV Wonder Pro - Conexant */
+#define TUNER_PHILIPS_4IN1             44      /* ATI TV Wonder Pro - Conexant */
 /* Microtune mergeged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */
-#define TUNER_MICROTUNE_4049FM5  45
-#define TUNER_LG_NTSC_TAPE       47
-
-#define TUNER_TNF_8831BGFF       48
-#define TUNER_MICROTUNE_4042FI5  49    /* DViCO FusionHDTV 3 Gold-Q - 4042 FI5 (3X 8147) */
-#define TUNER_TCL_2002N          50
-#define TUNER_PHILIPS_FM1256_IH3   51
-
-#define TUNER_THOMSON_DTT7610    52
-#define TUNER_PHILIPS_FQ1286     53
-#define TUNER_PHILIPS_TDA8290    54
-#define TUNER_LG_PAL_TAPE        55    /* Hauppauge PVR-150 PAL */
-
-#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
-#define TUNER_PHILIPS_FQ1236A_MK4   57   /* Hauppauge PVR-500MCE NTSC */
-
-#define TUNER_YMEC_TVF_8531MF 58
-#define TUNER_YMEC_TVF_5533MF 59       /* Pixelview Pro Ultra NTSC */
-#define TUNER_THOMSON_DTT7611 60       /* DViCO FusionHDTV 3 Gold-T */
-#define TUNER_TENA_9533_DI    61
-
-#define TUNER_TEA5767         62       /* Only FM Radio Tuner */
-#define TUNER_PHILIPS_FMD1216ME_MK3 63
-#define TUNER_LG_TDVS_H062F   64       /* DViCO FusionHDTV 5 */
-#define TUNER_YMEC_TVF66T5_B_DFF 65    /* Acorp Y878F */
+#define TUNER_MICROTUNE_4049FM5        45
+#define TUNER_MICROTUNE_4042_FI5       46
+#define TUNER_LG_NTSC_TAPE             47
+
+#define TUNER_TNF_8831BGFF             48
+#define TUNER_MICROTUNE_4042FI5                49      /* DViCO FusionHDTV 3 Gold-Q - 4042 FI5 (3X 8147) */
+#define TUNER_TCL_2002N                        50
+#define TUNER_PHILIPS_FM1256_IH3       51
+
+#define TUNER_THOMSON_DTT7610          52
+#define TUNER_PHILIPS_FQ1286           53
+#define TUNER_PHILIPS_TDA8290          54
+#define TUNER_LG_PAL_TAPE              55      /* Hauppauge PVR-150 PAL */
+
+#define TUNER_PHILIPS_FQ1216AME_MK4    56      /* Hauppauge PVR-150 PAL */
+#define TUNER_PHILIPS_FQ1236A_MK4      57      /* Hauppauge PVR-500MCE NTSC */
+#define TUNER_YMEC_TVF_8531MF          58
+#define TUNER_YMEC_TVF_5533MF          59      /* Pixelview Pro Ultra NTSC */
+
+#define TUNER_THOMSON_DTT7611          60      /* DViCO FusionHDTV 3 Gold-T */
+#define TUNER_TENA_9533_DI             61
+#define TUNER_TEA5767                  62      /* Only FM Radio Tuner */
+#define TUNER_PHILIPS_FMD1216ME_MK3    63
+
+#define TUNER_LG_TDVS_H062F            64      /* DViCO FusionHDTV 5 */
+#define TUNER_YMEC_TVF66T5_B_DFF       65      /* Acorp Y878F */
+#define TUNER_LG_NTSC_TALN_MINI                66
 
 #define NOTUNER 0
 #define PAL     1      /* PAL_BG */
 #define NTSC    3
 #define SECAM   4
 #define ATSC    5
-#define RADIO  6
+#define RADIO   6
 
 #define NoTuner 0
 #define Philips 1
 #define THOMSON 12
 
 #define TUNER_SET_TYPE_ADDR          _IOW('T',3,int)
+#define TUNER_SET_STANDBY            _IOW('T',4,int)
 #define TDA9887_SET_CONFIG           _IOW('t',5,int)
 
 /* tv card specific */
 
 #ifdef __KERNEL__
 
-#define I2C_ADDR_TDA8290        0x4b
-#define I2C_ADDR_TDA8275        0x61
-
 enum tuner_mode {
        T_UNINITIALIZED = 0,
        T_RADIO         = 1 << V4L2_TUNER_RADIO,
@@ -165,21 +163,21 @@ enum tuner_mode {
 };
 
 struct tuner_setup {
-       unsigned short          addr;
-       unsigned int            type;
-       unsigned int            mode_mask;
+       unsigned short  addr;
+       unsigned int    type;
+       unsigned int    mode_mask;
 };
 
 struct tuner {
        /* device */
        struct i2c_client i2c;
 
-       unsigned int type;            /* chip type */
+       unsigned int type;      /* chip type */
 
-       unsigned int          mode;
-       unsigned int          mode_mask; /* Combination of allowable modes */
+       unsigned int mode;
+       unsigned int mode_mask; /* Combination of allowable modes */
 
-       unsigned int freq;            /* keep track of the current settings */
+       unsigned int freq;      /* keep track of the current settings */
        unsigned int audmode;
        v4l2_std_id  std;
 
@@ -198,6 +196,7 @@ struct tuner {
        void (*radio_freq)(struct i2c_client *c, unsigned int freq);
        int  (*has_signal)(struct i2c_client *c);
        int  (*is_stereo)(struct i2c_client *c);
+       void (*standby)(struct i2c_client *c);
 };
 
 extern unsigned int tuner_debug;
@@ -209,16 +208,20 @@ extern int tea5767_tuner_init(struct i2c_client *c);
 extern int default_tuner_init(struct i2c_client *c);
 extern int tea5767_autodetection(struct i2c_client *c);
 
-#define tuner_warn(fmt, arg...) \
-       dev_printk(KERN_WARNING , &t->i2c.dev , fmt , ## arg)
-#define tuner_info(fmt, arg...) \
-       dev_printk(KERN_INFO , &t->i2c.dev , fmt , ## arg)
-#define tuner_dbg(fmt, arg...) \
-       if (tuner_debug) dev_printk(KERN_DEBUG , &t->i2c.dev , fmt , ## arg)
+#define tuner_warn(fmt, arg...) do {\
+       printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \
+                        t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
+#define tuner_info(fmt, arg...) do {\
+       printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \
+                        t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
+#define tuner_dbg(fmt, arg...) do {\
+       if (tuner_debug) \
+                printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \
+                        t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
 
 #endif /* __KERNEL__ */
 
-#endif
+#endif /* _TUNER_H */
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 854a2c2f105be81a45797a2d0420d26a6e504421..e2035c7da09480551a93555ab8cd36524a8982d7 100644 (file)
@@ -1,18 +1,21 @@
 /*
- * $Id: tveeprom.h,v 1.2 2005/06/12 04:19:19 mchehab Exp $
  */
 
 struct tveeprom {
        u32 has_radio;
+       u32 has_ir;     /* 0: no IR, 1: IR present, 2: unknown */
 
        u32 tuner_type;
        u32 tuner_formats;
 
+       u32 tuner2_type;
+       u32 tuner2_formats;
+
        u32 digitizer;
        u32 digitizer_formats;
 
        u32 audio_processor;
-       /* a_p_fmts? */
+       u32 decoder_processor;
 
        u32 model;
        u32 revision;
@@ -20,7 +23,7 @@ struct tveeprom {
        char rev_str[5];
 };
 
-void tveeprom_hauppauge_analog(struct tveeprom *tvee,
+void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
                               unsigned char *eeprom_data);
 
 int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len);
index ae6da6de98ded4600c7e502fe6b16265dc0bc612..ae8d7a0004402715d015e2962287a9a9c9161f00 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * $Id: video-buf.h,v 1.9 2004/11/07 13:17:15 kraxel Exp $
  *
  * generic helper functions for video4linux capture buffers, to handle
  * memory management and PCI DMA.  Right now bttv + saa7134 use it.
index b707a603351b2217b6aecaeca3b7e81155b38d9e..cb8b6e6ce66c9dc192aefc705aaa4999b07b82b8 100644 (file)
@@ -151,6 +151,8 @@ struct pcmcia_device {
           uniquely define a pcmcia_device */
        struct pcmcia_socket    *socket;
 
+       char                    *devname;
+
        u8                      device_no;
 
        /* the hardware "function" device; certain subdevices can
index 77fe9039209b1612590fcf7923fc1faaf8b1c8a7..5308683c8c41a792f4e02c353056f2b69fab974d 100644 (file)
@@ -290,6 +290,7 @@ struct ib_cm_id {
        enum ib_cm_lap_state    lap_state;      /* internal CM/debug use */
        __be32                  local_id;
        __be32                  remote_id;
+       u32                     remote_cm_qpn;  /* 1 unless redirected */
 };
 
 /**
index fc6b1c18ffc698fae47992646c2abed213a9ac3a..53184a38fdf64c5cee649dc482ab2fc656a936cf 100644 (file)
@@ -173,6 +173,27 @@ struct ib_vendor_mad {
        u8                      data[216];
 };
 
+struct ib_class_port_info
+{
+       u8                      base_version;
+       u8                      class_version;
+       __be16                  capability_mask;
+       u8                      reserved[3];
+       u8                      resp_time_value;
+       u8                      redirect_gid[16];
+       __be32                  redirect_tcslfl;
+       __be16                  redirect_lid;
+       __be16                  redirect_pkey;
+       __be32                  redirect_qp;
+       __be32                  redirect_qkey;
+       u8                      trap_gid[16];
+       __be32                  trap_tcslfl;
+       __be16                  trap_lid;
+       __be16                  trap_pkey;
+       __be32                  trap_hlqp;
+       __be32                  trap_qkey;
+};
+
 /**
  * ib_mad_send_buf - MAD data buffer and work request for sends.
  * @mad: References an allocated MAD data buffer.  The size of the data
index c022edfc49da013844509e4b4ff22368449cae9c..a7555c800ecf94667bb8c0d104829f323e34fa19 100644 (file)
@@ -46,7 +46,36 @@ enum {
 
        IB_SA_METHOD_GET_TABLE          = 0x12,
        IB_SA_METHOD_GET_TABLE_RESP     = 0x92,
-       IB_SA_METHOD_DELETE             = 0x15
+       IB_SA_METHOD_DELETE             = 0x15,
+       IB_SA_METHOD_DELETE_RESP        = 0x95,
+       IB_SA_METHOD_GET_MULTI          = 0x14,
+       IB_SA_METHOD_GET_MULTI_RESP     = 0x94,
+       IB_SA_METHOD_GET_TRACE_TBL      = 0x13
+};
+
+enum {
+       IB_SA_ATTR_CLASS_PORTINFO    = 0x01,
+       IB_SA_ATTR_NOTICE            = 0x02,
+       IB_SA_ATTR_INFORM_INFO       = 0x03,
+       IB_SA_ATTR_NODE_REC          = 0x11,
+       IB_SA_ATTR_PORT_INFO_REC     = 0x12,
+       IB_SA_ATTR_SL2VL_REC         = 0x13,
+       IB_SA_ATTR_SWITCH_REC        = 0x14,
+       IB_SA_ATTR_LINEAR_FDB_REC    = 0x15,
+       IB_SA_ATTR_RANDOM_FDB_REC    = 0x16,
+       IB_SA_ATTR_MCAST_FDB_REC     = 0x17,
+       IB_SA_ATTR_SM_INFO_REC       = 0x18,
+       IB_SA_ATTR_LINK_REC          = 0x20,
+       IB_SA_ATTR_GUID_INFO_REC     = 0x30,
+       IB_SA_ATTR_SERVICE_REC       = 0x31,
+       IB_SA_ATTR_PARTITION_REC     = 0x33,
+       IB_SA_ATTR_PATH_REC          = 0x35,
+       IB_SA_ATTR_VL_ARB_REC        = 0x36,
+       IB_SA_ATTR_MC_MEMBER_REC     = 0x38,
+       IB_SA_ATTR_TRACE_REC         = 0x39,
+       IB_SA_ATTR_MULTI_PATH_REC    = 0x3a,
+       IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b,
+       IB_SA_ATTR_INFORM_INFO_REC   = 0xf3
 };
 
 enum ib_sa_selector {
index 72182d16778b5dabd3a64157b17e8eb9cb0d267f..e4d1654276ad95b59d6a92f6db365b2836f18117 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -37,7 +38,7 @@
 
 #include <linux/types.h>
 
-#define IB_USER_CM_ABI_VERSION 1
+#define IB_USER_CM_ABI_VERSION 2
 
 enum {
        IB_USER_CM_CMD_CREATE_ID,
@@ -60,6 +61,7 @@ enum {
        IB_USER_CM_CMD_SEND_SIDR_REP,
 
        IB_USER_CM_CMD_EVENT,
+       IB_USER_CM_CMD_INIT_QP_ATTR,
 };
 /*
  * command ABI structures.
@@ -71,6 +73,7 @@ struct ib_ucm_cmd_hdr {
 };
 
 struct ib_ucm_create_id {
+       __u64 uid;
        __u64 response;
 };
 
@@ -79,9 +82,14 @@ struct ib_ucm_create_id_resp {
 };
 
 struct ib_ucm_destroy_id {
+       __u64 response;
        __u32 id;
 };
 
+struct ib_ucm_destroy_id_resp {
+       __u32 events_reported;
+};
+
 struct ib_ucm_attr_id {
        __u64 response;
        __u32 id;
@@ -94,6 +102,64 @@ struct ib_ucm_attr_id_resp {
        __be32 remote_id;
 };
 
+struct ib_ucm_init_qp_attr {
+       __u64 response;
+       __u32 id;
+       __u32 qp_state;
+};
+
+struct ib_ucm_ah_attr {
+       __u8    grh_dgid[16];
+       __u32   grh_flow_label;
+       __u16   dlid;
+       __u16   reserved;
+       __u8    grh_sgid_index;
+       __u8    grh_hop_limit;
+       __u8    grh_traffic_class;
+       __u8    sl;
+       __u8    src_path_bits;
+       __u8    static_rate;
+       __u8    is_global;
+       __u8    port_num;
+};
+
+struct ib_ucm_init_qp_attr_resp {
+       __u32   qp_attr_mask;
+       __u32   qp_state;
+       __u32   cur_qp_state;
+       __u32   path_mtu;
+       __u32   path_mig_state;
+       __u32   qkey;
+       __u32   rq_psn;
+       __u32   sq_psn;
+       __u32   dest_qp_num;
+       __u32   qp_access_flags;
+
+       struct ib_ucm_ah_attr   ah_attr;
+       struct ib_ucm_ah_attr   alt_ah_attr;
+
+       /* ib_qp_cap */
+       __u32   max_send_wr;
+       __u32   max_recv_wr;
+       __u32   max_send_sge;
+       __u32   max_recv_sge;
+       __u32   max_inline_data;
+
+       __u16   pkey_index;
+       __u16   alt_pkey_index;
+       __u8    en_sqd_async_notify;
+       __u8    sq_draining;
+       __u8    max_rd_atomic;
+       __u8    max_dest_rd_atomic;
+       __u8    min_rnr_timer;
+       __u8    port_num;
+       __u8    timeout;
+       __u8    retry_cnt;
+       __u8    rnr_retry;
+       __u8    alt_port_num;
+       __u8    alt_timeout;
+};
+
 struct ib_ucm_listen {
        __be64 service_id;
        __be64 service_mask;
@@ -157,6 +223,7 @@ struct ib_ucm_req {
 };
 
 struct ib_ucm_rep {
+       __u64 uid;
        __u64 data;
        __u32 id;
        __u32 qpn;
@@ -232,7 +299,6 @@ struct ib_ucm_event_get {
 };
 
 struct ib_ucm_req_event_resp {
-       __u32                  listen_id;
        /* device */
        /* port */
        struct ib_ucm_path_rec primary_path;
@@ -287,7 +353,6 @@ struct ib_ucm_apr_event_resp {
 };
 
 struct ib_ucm_sidr_req_event_resp {
-       __u32 listen_id;
        /* device */
        /* port */
        __u16 pkey;
@@ -307,6 +372,7 @@ struct ib_ucm_sidr_rep_event_resp {
 #define IB_UCM_PRES_ALTERNATE 0x08
 
 struct ib_ucm_event_resp {
+       __u64 uid;
        __u32 id;
        __u32 event;
        __u32 present;
index 7ebb01c8f99638597123d4f4185ebd14be9ab1fa..fd85725391a4e80a1267ffbf57190c0e356ace02 100644 (file)
@@ -42,7 +42,7 @@
  * Increment this value if any changes that break userspace ABI
  * compatibility are made.
  */
-#define IB_USER_VERBS_ABI_VERSION      1
+#define IB_USER_VERBS_ABI_VERSION      2
 
 enum {
        IB_USER_VERBS_CMD_QUERY_PARAMS,
@@ -292,7 +292,14 @@ struct ib_uverbs_create_cq_resp {
 };
 
 struct ib_uverbs_destroy_cq {
+       __u64 response;
        __u32 cq_handle;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_cq_resp {
+       __u32 comp_events_reported;
+       __u32 async_events_reported;
 };
 
 struct ib_uverbs_create_qp {
@@ -372,7 +379,13 @@ struct ib_uverbs_modify_qp_resp {
 };
 
 struct ib_uverbs_destroy_qp {
+       __u64 response;
        __u32 qp_handle;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_qp_resp {
+       __u32 events_reported;
 };
 
 struct ib_uverbs_attach_mcast {
@@ -416,7 +429,13 @@ struct ib_uverbs_modify_srq {
 };
 
 struct ib_uverbs_destroy_srq {
+       __u64 response;
        __u32 srq_handle;
+       __u32 reserved;
+};
+
+struct ib_uverbs_destroy_srq_resp {
+       __u32 events_reported;
 };
 
 #endif /* IB_USER_VERBS_H */
index 389e8ebe9c191cf550fe824905c5f8f465f4832c..d6361dab0370856e3fb3638b442798c435a5c5af 100644 (file)
@@ -910,11 +910,10 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format);
  * Returns 1 if the given PCM format is CPU-endian, 0 if
  * opposite, or a negative error code if endian not specified.
  */
-/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */
 #ifdef SNDRV_LITTLE_ENDIAN
-#define snd_pcm_format_cpu_endian      snd_pcm_format_little_endian
+#define snd_pcm_format_cpu_endian(format) snd_pcm_format_little_endian(format)
 #else
-#define snd_pcm_format_cpu_endian      snd_pcm_format_big_endian
+#define snd_pcm_format_cpu_endian(format) snd_pcm_format_big_endian(format)
 #endif
 int snd_pcm_format_width(snd_pcm_format_t format);                     /* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);            /* in bits */
index ad3c3be33c0391ddb3a0b613c8e8f0dab6cd4b0c..b82e408e758f498735893c979c0a04b3aa1922a9 100644 (file)
@@ -34,9 +34,7 @@ struct snd_tea575x_ops {
 struct snd_tea575x {
        snd_card_t *card;
        struct video_device vd;         /* video device */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
        struct file_operations fops;
-#endif
        int dev_nr;                     /* requested device number + 1 */
        int vd_registered;              /* video device is registered */
        int tea5759;                    /* 5759 chip is present */
diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h
new file mode 100644 (file)
index 0000000..a994823
--- /dev/null
@@ -0,0 +1,171 @@
+
+#ifndef CYBLAFB_DEBUG
+#define CYBLAFB_DEBUG 0
+#endif
+
+#if CYBLAFB_DEBUG
+#define debug(f,a...)  printk("%s:" f,  __FUNCTION__ , ## a);
+#else
+#define debug(f,a...)
+#endif
+
+#define output(f, a...) printk("cyblafb: " f, ## a)
+
+#define Kb     (1024)
+#define Mb     (Kb*Kb)
+
+/* PCI IDS of supported cards temporarily here */
+
+#define CYBERBLADEi1   0x8500
+
+/* these defines are for 'lcd' variable */
+#define LCD_STRETCH    0
+#define LCD_CENTER     1
+#define LCD_BIOS       2
+
+/* display types */
+#define DISPLAY_CRT    0
+#define DISPLAY_FP     1
+
+#define ROP_S  0xCC
+
+#define point(x,y) ((y)<<16|(x))
+
+//
+// Attribute Regs, ARxx, 3c0/3c1
+//
+#define AR00   0x00
+#define AR01   0x01
+#define AR02   0x02
+#define AR03   0x03
+#define AR04   0x04
+#define AR05   0x05
+#define AR06   0x06
+#define AR07   0x07
+#define AR08   0x08
+#define AR09   0x09
+#define AR0A   0x0A
+#define AR0B   0x0B
+#define AR0C   0x0C
+#define AR0D   0x0D
+#define AR0E   0x0E
+#define AR0F   0x0F
+#define AR10   0x10
+#define AR12   0x12
+#define AR13   0x13
+
+//
+// Sequencer Regs, SRxx, 3c4/3c5
+//
+#define SR00   0x00
+#define SR01   0x01
+#define SR02   0x02
+#define SR03   0x03
+#define SR04   0x04
+#define SR0D   0x0D
+#define SR0E   0x0E
+#define SR11   0x11
+#define SR18   0x18
+#define SR19   0x19
+
+//
+//
+//
+#define CR00   0x00
+#define CR01   0x01
+#define CR02   0x02
+#define CR03   0x03
+#define CR04   0x04
+#define CR05   0x05
+#define CR06   0x06
+#define CR07   0x07
+#define CR08   0x08
+#define CR09   0x09
+#define CR0A   0x0A
+#define CR0B   0x0B
+#define CR0C   0x0C
+#define CR0D   0x0D
+#define CR0E   0x0E
+#define CR0F   0x0F
+#define CR10   0x10
+#define CR11   0x11
+#define CR12   0x12
+#define CR13   0x13
+#define CR14   0x14
+#define CR15   0x15
+#define CR16   0x16
+#define CR17   0x17
+#define CR18   0x18
+#define CR19   0x19
+#define CR1A   0x1A
+#define CR1B   0x1B
+#define CR1C   0x1C
+#define CR1D   0x1D
+#define CR1E   0x1E
+#define CR1F   0x1F
+#define CR20   0x20
+#define CR21   0x21
+#define CR27   0x27
+#define CR29   0x29
+#define CR2A   0x2A
+#define CR2B   0x2B
+#define CR2D   0x2D
+#define CR2F   0x2F
+#define CR36   0x36
+#define CR38   0x38
+#define CR39   0x39
+#define CR3A   0x3A
+#define CR55   0x55
+#define CR56   0x56
+#define CR57   0x57
+#define CR58   0x58
+
+//
+//
+//
+
+#define GR00   0x01
+#define GR01   0x01
+#define GR02   0x02
+#define GR03   0x03
+#define GR04   0x04
+#define GR05   0x05
+#define GR06   0x06
+#define GR07   0x07
+#define GR08   0x08
+#define GR0F   0x0F
+#define GR20   0x20
+#define GR23   0x23
+#define GR2F   0x2F
+#define GR30   0x30
+#define GR31   0x31
+#define GR33   0x33
+#define GR52   0x52
+#define GR53   0x53
+#define GR5D   0x5d
+
+
+//
+// Graphics Engine
+//
+#define GEBase 0x2100          // could be mapped elsewhere if we like it
+#define GE00   (GEBase+0x00)   // source 1, p 111
+#define GE04   (GEBase+0x04)   // source 2, p 111
+#define GE08   (GEBase+0x08)   // destination 1, p 111
+#define GE0C   (GEBase+0x0C)   // destination 2, p 112
+#define GE20   (GEBase+0x20)   // engine status, p 113
+#define GE24   (GEBase+0x24)   // reset all GE pointers
+#define GE44   (GEBase+0x44)   // command register, p 126
+#define GE48   (GEBase+0x48)   // raster operation, p 127
+#define GE60   (GEBase+0x60)   // foreground color, p 128
+#define GE64   (GEBase+0x64)   // background color, p 128
+#define GE6C   (GEBase+0x6C)   // Pattern and Style, p 129, ok
+#define GE9C   (GEBase+0x9C)   // pixel engine data port, p 125
+#define GEB8   (GEBase+0xB8)   // Destination Stride / Buffer Base 0, p 133
+#define GEBC   (GEBase+0xBC)   // Destination Stride / Buffer Base 1, p 133
+#define GEC0   (GEBase+0xC0)   // Destination Stride / Buffer Base 2, p 133
+#define GEC4   (GEBase+0xC4)   // Destination Stride / Buffer Base 3, p 133
+#define GEC8   (GEBase+0xC8)   // Source Stride / Buffer Base 0, p 133
+#define GECC   (GEBase+0xCC)   // Source Stride / Buffer Base 1, p 133
+#define GED0   (GEBase+0xD0)   // Source Stride / Buffer Base 2, p 133
+#define GED4   (GEBase+0xD4)   // Source Stride / Buffer Base 3, p 133
index 136bf791643d1b148deec9242d972946dc047a7c..e402eb5b3c7a2b74f08da85c26d5e947989f65d1 100644 (file)
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
+ * sisfb.h - definitions for the SiS framebuffer driver
+ *
+ * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
  *
  * 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
@@ -16,8 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  */
 
-#ifndef _LINUX_SISFB
-#define _LINUX_SISFB
+#ifndef _LINUX_SISFB_H_
+#define _LINUX_SISFB_H_
 
 #include <asm/ioctl.h>
 #include <asm/types.h>
 /*                   PUBLIC                   */
 /**********************************************/
 
-/* vbflags */
-#define CRT2_DEFAULT            0x00000001
-#define CRT2_LCD                0x00000002  /* TW: Never change the order of the CRT2_XXX entries */
-#define CRT2_TV                 0x00000004  /*     (see SISCycleCRT2Type())                       */
-#define CRT2_VGA                0x00000008
-#define TV_NTSC                 0x00000010
-#define TV_PAL                  0x00000020
-#define TV_HIVISION             0x00000040
-#define TV_YPBPR                0x00000080
-#define TV_AVIDEO               0x00000100
-#define TV_SVIDEO               0x00000200
-#define TV_SCART                0x00000400
-#define VB_CONEXANT            0x00000800      /* 661 series only */
-#define VB_TRUMPION            VB_CONEXANT     /* 300 series only */
-#define TV_PALM                 0x00001000
-#define TV_PALN                 0x00002000
+/* vbflags, public (others in sis.h) */
+#define CRT2_DEFAULT           0x00000001
+#define CRT2_LCD               0x00000002
+#define CRT2_TV                        0x00000004
+#define CRT2_VGA               0x00000008
+#define TV_NTSC                        0x00000010
+#define TV_PAL                 0x00000020
+#define TV_HIVISION            0x00000040
+#define TV_YPBPR               0x00000080
+#define TV_AVIDEO              0x00000100
+#define TV_SVIDEO              0x00000200
+#define TV_SCART               0x00000400
+#define TV_PALM                        0x00001000
+#define TV_PALN                        0x00002000
 #define TV_NTSCJ               0x00001000
-#define VB_302ELV              0x00004000
-#define TV_CHSCART              0x00008000
-#define TV_CHYPBPR525I          0x00010000
+#define TV_CHSCART             0x00008000
+#define TV_CHYPBPR525I         0x00010000
 #define CRT1_VGA               0x00000000
 #define CRT1_LCDA              0x00020000
 #define VGA2_CONNECTED          0x00040000
-#define VB_DISPTYPE_CRT1       0x00080000      /* CRT1 connected and used */
-#define VB_301                  0x00100000     /* Video bridge type */
-#define VB_301B                 0x00200000
-#define VB_302B                 0x00400000
-#define VB_30xBDH              0x00800000      /* 30xB DH version (w/o LCD support) */
-#define VB_LVDS                 0x01000000
-#define VB_CHRONTEL             0x02000000
-#define VB_301LV                0x04000000
-#define VB_302LV                0x08000000
-#define VB_301C                        0x10000000
-#define VB_SINGLE_MODE          0x20000000     /* CRT1 or CRT2; determined by DISPTYPE_CRTx */
-#define VB_MIRROR_MODE         0x40000000      /* CRT1 + CRT2 identical (mirror mode) */
-#define VB_DUALVIEW_MODE       0x80000000      /* CRT1 + CRT2 independent (dual head mode) */
+#define VB_DISPTYPE_CRT1       0x00080000      /* CRT1 connected and used */
+#define VB_SINGLE_MODE         0x20000000      /* CRT1 or CRT2; determined by DISPTYPE_CRTx */
+#define VB_MIRROR_MODE         0x40000000      /* CRT1 + CRT2 identical (mirror mode) */
+#define VB_DUALVIEW_MODE       0x80000000      /* CRT1 + CRT2 independent (dual head mode) */
 
 /* Aliases: */
 #define CRT2_ENABLE            (CRT2_LCD | CRT2_TV | CRT2_VGA)
-#define TV_STANDARD             (TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ)
-#define TV_INTERFACE            (TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_CHSCART|TV_CHYPBPR525I)
+#define TV_STANDARD            (TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ)
+#define TV_INTERFACE           (TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_CHSCART|TV_CHYPBPR525I)
 
 /* Only if TV_YPBPR is set: */
 #define TV_YPBPR525I           TV_NTSC
 #define TV_YPBPR1080I          TV_PALN
 #define TV_YPBPRALL            (TV_YPBPR525I | TV_YPBPR525P | TV_YPBPR750P | TV_YPBPR1080I)
 
-#define VB_SISBRIDGE            (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV|VB_302ELV)
-#define VB_SISTVBRIDGE          (VB_301|VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)
-#define VB_VIDEOBRIDGE         (VB_SISBRIDGE | VB_LVDS | VB_CHRONTEL | VB_CONEXANT)
-
 #define VB_DISPTYPE_DISP2      CRT2_ENABLE
 #define VB_DISPTYPE_CRT2       CRT2_ENABLE
 #define VB_DISPTYPE_DISP1      VB_DISPTYPE_CRT1
 #define VB_DISPMODE_SINGLE     VB_SINGLE_MODE
 #define VB_DISPMODE_MIRROR     VB_MIRROR_MODE
 #define VB_DISPMODE_DUAL       VB_DUALVIEW_MODE
-#define VB_DISPLAY_MODE        (SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
+#define VB_DISPLAY_MODE                (SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
 
 /* Structure argument for SISFB_GET_INFO ioctl  */
-typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
-
-struct _SISFB_INFO {
-       __u32   sisfb_id;               /* for identifying sisfb */
+struct sisfb_info {
+       __u32   sisfb_id;               /* for identifying sisfb */
 #ifndef SISFB_ID
 #define SISFB_ID         0x53495346    /* Identify myself with 'SISF' */
 #endif
-       __u32   chip_id;                /* PCI-ID of detected chip */
-       __u32   memory;                 /* video memory in KB which sisfb manages */
-       __u32   heapstart;              /* heap start (= sisfb "mem" argument) in KB */
+       __u32   chip_id;                /* PCI-ID of detected chip */
+       __u32   memory;                 /* total video memory in KB */
+       __u32   heapstart;              /* heap start offset in KB */
        __u8    fbvidmode;              /* current sisfb mode */
 
-       __u8    sisfb_version;
-       __u8    sisfb_revision;
-       __u8    sisfb_patchlevel;
+       __u8    sisfb_version;
+       __u8    sisfb_revision;
+       __u8    sisfb_patchlevel;
 
-       __u8    sisfb_caps;             /* sisfb capabilities */
+       __u8    sisfb_caps;             /* sisfb capabilities */
 
        __u32   sisfb_tqlen;            /* turbo queue length (in KB) */
 
-       __u32   sisfb_pcibus;           /* The card's PCI ID */
-       __u32   sisfb_pcislot;
-       __u32   sisfb_pcifunc;
+       __u32   sisfb_pcibus;           /* The card's PCI ID */
+       __u32   sisfb_pcislot;
+       __u32   sisfb_pcifunc;
+
+       __u8    sisfb_lcdpdc;           /* PanelDelayCompensation */
+
+       __u8    sisfb_lcda;             /* Detected status of LCDA for low res/text modes */
+
+       __u32   sisfb_vbflags;
+       __u32   sisfb_currentvbflags;
+
+       __u32   sisfb_scalelcd;
+       __u32   sisfb_specialtiming;
+
+       __u8    sisfb_haveemi;
+       __u8    sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+       __u8    sisfb_haveemilcd;
 
-       __u8    sisfb_lcdpdc;           /* PanelDelayCompensation */
+       __u8    sisfb_lcdpdca;          /* PanelDelayCompensation for LCD-via-CRT1 */
 
-       __u8    sisfb_lcda;             /* Detected status of LCDA for low res/text modes */
+       __u16   sisfb_tvxpos, sisfb_tvypos;     /* Warning: Values + 32 ! */
 
-       __u32   sisfb_vbflags;
-       __u32   sisfb_currentvbflags;
+       __u32   sisfb_heapsize;         /* heap size (in KB) */
+       __u32   sisfb_videooffset;      /* Offset of viewport in video memory (in bytes) */
 
-       __u32   sisfb_scalelcd;
-       __u32   sisfb_specialtiming;
+       __u32   sisfb_curfstn;          /* currently running FSTN/DSTN mode */
+       __u32   sisfb_curdstn;
 
-       __u8    sisfb_haveemi;
-       __u8    sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-       __u8    sisfb_haveemilcd;
+       __u16   sisfb_pci_vendor;       /* PCI vendor (SiS or XGI) */
 
-       __u8    sisfb_lcdpdca;          /* PanelDelayCompensation for LCD-via-CRT1 */
+       __u32   sisfb_vbflags2;         /* ivideo->vbflags2 */
 
-       __u16   sisfb_tvxpos, sisfb_tvypos;  /* Warning: Values + 32 ! */
+       __u8    sisfb_can_post;         /* sisfb can POST this card */
+       __u8    sisfb_card_posted;      /* card is POSTED */
+       __u8    sisfb_was_boot_device;  /* This card was the boot video device (ie is primary) */
 
-       __u8    reserved[208];          /* for future use */
+       __u8    reserved[183];          /* for future use */
+};
+
+#define SISFB_CMD_GETVBFLAGS   0x55AA0001      /* no arg; result[1] = vbflags */
+#define SISFB_CMD_SWITCHCRT1   0x55AA0010      /* arg[0]: 99 = query, 0 = off, 1 = on */
+/* more to come */
+
+#define SISFB_CMD_ERR_OK       0x80000000      /* command succeeded */
+#define SISFB_CMD_ERR_LOCKED   0x80000001      /* sisfb is locked */
+#define SISFB_CMD_ERR_EARLY    0x80000002      /* request before sisfb took over gfx system */
+#define SISFB_CMD_ERR_NOVB     0x80000003      /* No video bridge */
+#define SISFB_CMD_ERR_NOCRT2   0x80000004      /* can't change CRT1 status, CRT2 disabled */
+/* more to come */
+#define SISFB_CMD_ERR_UNKNOWN   0x8000ffff     /* Unknown command */
+#define SISFB_CMD_ERR_OTHER    0x80010000      /* Other error */
+
+/* Argument for SISFB_CMD ioctl */
+struct sisfb_cmd {
+       __u32  sisfb_cmd;
+       __u32  sisfb_arg[16];
+       __u32  sisfb_result[4];
 };
 
 /* Addtional IOCTLs for communication sisfb <> X driver                */
 /* If changing this, vgatypes.h must also be changed (for X driver)    */
 
 /* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_SIZE    _IOR(0xF3,0x00,__u32)
-#define SISFB_GET_INFO         _IOR(0xF3,0x01,struct _SISFB_INFO)
+#define SISFB_GET_INFO_SIZE    _IOR(0xF3,0x00,__u32)
+#define SISFB_GET_INFO         _IOR(0xF3,0x01,struct sisfb_info)
 
 /* ioctrl to get current vertical retrace status */
-#define SISFB_GET_VBRSTATUS    _IOR(0xF3,0x02,__u32)
+#define SISFB_GET_VBRSTATUS    _IOR(0xF3,0x02,__u32)
 
 /* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
-#define SISFB_GET_AUTOMAXIMIZE         _IOR(0xF3,0x03,__u32)
-#define SISFB_SET_AUTOMAXIMIZE         _IOW(0xF3,0x03,__u32)
+#define SISFB_GET_AUTOMAXIMIZE _IOR(0xF3,0x03,__u32)
+#define SISFB_SET_AUTOMAXIMIZE _IOW(0xF3,0x03,__u32)
 
 /* ioctls to relocate TV output (x=D[31:16], y=D[15:0], + 32)*/
-#define SISFB_GET_TVPOSOFFSET   _IOR(0xF3,0x04,__u32)
-#define SISFB_SET_TVPOSOFFSET   _IOW(0xF3,0x04,__u32)
+#define SISFB_GET_TVPOSOFFSET  _IOR(0xF3,0x04,__u32)
+#define SISFB_SET_TVPOSOFFSET  _IOW(0xF3,0x04,__u32)
+
+/* ioctl for internal sisfb commands (sisfbctrl) */
+#define SISFB_COMMAND          _IOWR(0xF3,0x05,struct sisfb_cmd)
 
 /* ioctl for locking sisfb (no register access during lock) */
 /* As of now, only used to avoid register access during
  * the ioctls listed above.
  */
-#define SISFB_SET_LOCK         _IOW(0xF3,0x06,__u32)
-
-/* more to come soon */
+#define SISFB_SET_LOCK         _IOW(0xF3,0x06,__u32)
 
 /* ioctls 0xF3 up to 0x3F reserved for sisfb */
 
@@ -165,7 +184,7 @@ struct _SISFB_INFO {
 /* The following are deprecated and should not be used anymore: */
 /****************************************************************/
 /* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO_OLD        _IOR('n',0xF8,__u32)
+#define SISFB_GET_INFO_OLD        _IOR('n',0xF8,__u32)
 /* ioctrl to get current vertical retrace status */
 #define SISFB_GET_VBRSTATUS_OLD           _IOR('n',0xF9,__u32)
 /* ioctl to enable/disable panning auto-maximize (like nomax parameter) */
@@ -177,8 +196,8 @@ struct _SISFB_INFO {
 
 /* For fb memory manager (FBIO_ALLOC, FBIO_FREE) */
 struct sis_memreq {
-       __u32   offset;
-       __u32   size;
+       __u32   offset;
+       __u32   size;
 };
 
 /**********************************************/
@@ -187,12 +206,19 @@ struct sis_memreq {
 /**********************************************/
 
 #ifdef __KERNEL__
+
+#include <linux/pci.h>
+
 #define        UNKNOWN_VGA  0
 #define        SIS_300_VGA  1
 #define        SIS_315_VGA  2
 
+#define SISFB_HAVE_MALLOC_NEW
 extern void sis_malloc(struct sis_memreq *req);
+extern void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req);
+
 extern void sis_free(u32 base);
+extern void sis_free_new(struct pci_dev *pdev, u32 base);
 #endif
 
 #endif
index 0acf245f441d6640cbf8739211bb19dfd51e9d8c..3a926011507b8768ff9991b55837a3f7ee9f579e 100644 (file)
@@ -69,7 +69,7 @@ struct mqueue_inode_info {
 
        struct sigevent notify;
        pid_t notify_owner;
-       struct user_struct *user;       /* user who created, for accouting */
+       struct user_struct *user;       /* user who created, for accounting */
        struct sock *notify_sock;
        struct sk_buff *notify_cookie;
 
index 8d57a2f1226baa8034e8d93b7e4806d5a3f5fce1..ff4dc02ce17027f22dc4bf4027075653ee7f42bb 100644 (file)
@@ -12,6 +12,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o spinlock.o
+obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
index f70e6027cca9758c7ca35f3dc4bd89b7d97d5b14..b756f527497ea8c201d533df64ff053da0084d96 100644 (file)
@@ -165,7 +165,7 @@ out:
 }
 
 /*
- * Close the old accouting file (if currently open) and then replace
+ * Close the old accounting file (if currently open) and then replace
  * it with file (if non-NULL).
  *
  * NOTE: acct_globals.lock MUST be held on entry and exit.
@@ -199,11 +199,16 @@ static void acct_file_reopen(struct file *file)
        }
 }
 
-/*
- *  sys_acct() is the only system call needed to implement process
- *  accounting. It takes the name of the file where accounting records
- *  should be written. If the filename is NULL, accounting will be
- *  shutdown.
+/**
+ * sys_acct - enable/disable process accounting
+ * @name: file name for accounting records or NULL to shutdown accounting
+ *
+ * Returns 0 for success or negative errno values for failure.
+ *
+ * sys_acct() is the only system call needed to implement process
+ * accounting. It takes the name of the file where accounting records
+ * should be written. If the filename is NULL, accounting will be
+ * shutdown.
  */
 asmlinkage long sys_acct(const char __user *name)
 {
@@ -250,9 +255,12 @@ asmlinkage long sys_acct(const char __user *name)
        return (0);
 }
 
-/*
- * If the accouting is turned on for a file in the filesystem pointed
- * to by sb, turn accouting off.
+/**
+ * acct_auto_close - turn off a filesystem's accounting if it is on
+ * @sb: super block for the filesystem
+ *
+ * If the accounting is turned on for a file in the filesystem pointed
+ * to by sb, turn accounting off.
  */
 void acct_auto_close(struct super_block *sb)
 {
@@ -503,8 +511,11 @@ static void do_acct_process(long exitcode, struct file *file)
        set_fs(fs);
 }
 
-/*
+/**
  * acct_process - now just a wrapper around do_acct_process
+ * @exitcode: task exit code
+ *
+ * handles process accounting for an exiting task
  */
 void acct_process(long exitcode)
 {
@@ -530,9 +541,9 @@ void acct_process(long exitcode)
 }
 
 
-/*
- * acct_update_integrals
- *    -  update mm integral fields in task_struct
+/**
+ * acct_update_integrals - update mm integral fields in task_struct
+ * @tsk: task_struct for accounting
  */
 void acct_update_integrals(struct task_struct *tsk)
 {
@@ -547,9 +558,9 @@ void acct_update_integrals(struct task_struct *tsk)
        }
 }
 
-/*
- * acct_clear_integrals
- *    - clear the mm integral fields in task_struct
+/**
+ * acct_clear_integrals - clear the mm integral fields in task_struct
+ * @tsk: task_struct whose accounting fields are cleared
  */
 void acct_clear_integrals(struct task_struct *tsk)
 {
index ddfcaaa86623a0c02b68bc93a62c3d54bbe51762..102296e21ea86671f10fb922acf67feb81b22b1e 100644 (file)
@@ -48,8 +48,7 @@ static long compat_nanosleep_restart(struct restart_block *restart)
        if (!time_after(expire, now))
                return 0;
 
-       current->state = TASK_INTERRUPTIBLE;
-       expire = schedule_timeout(expire - now);
+       expire = schedule_timeout_interruptible(expire - now);
        if (expire == 0)
                return 0;
 
@@ -82,8 +81,7 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
                return -EINVAL;
 
        expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
-       current->state = TASK_INTERRUPTIBLE;
-       expire = schedule_timeout(expire);
+       expire = schedule_timeout_interruptible(expire);
        if (expire == 0)
                return 0;
 
@@ -795,8 +793,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
                        recalc_sigpending();
                        spin_unlock_irq(&current->sighand->siglock);
 
-                       current->state = TASK_INTERRUPTIBLE;
-                       timeout = schedule_timeout(timeout);
+                       timeout = schedule_timeout_interruptible(timeout);
 
                        spin_lock_irq(&current->sighand->siglock);
                        sig = dequeue_signal(current, &s, &info);
index 1f06e76901067ffa1c08d586d0128f64ad6d6c65..79866bc6b3a154d06c4b42daa3daec60aa96ebd9 100644 (file)
@@ -180,6 +180,42 @@ static struct super_block *cpuset_sb = NULL;
  */
 
 static DECLARE_MUTEX(cpuset_sem);
+static struct task_struct *cpuset_sem_owner;
+static int cpuset_sem_depth;
+
+/*
+ * The global cpuset semaphore cpuset_sem can be needed by the
+ * memory allocator to update a tasks mems_allowed (see the calls
+ * to cpuset_update_current_mems_allowed()) or to walk up the
+ * cpuset hierarchy to find a mem_exclusive cpuset see the calls
+ * to cpuset_excl_nodes_overlap()).
+ *
+ * But if the memory allocation is being done by cpuset.c code, it
+ * usually already holds cpuset_sem.  Double tripping on a kernel
+ * semaphore deadlocks the current task, and any other task that
+ * subsequently tries to obtain the lock.
+ *
+ * Run all up's and down's on cpuset_sem through the following
+ * wrappers, which will detect this nested locking, and avoid
+ * deadlocking.
+ */
+
+static inline void cpuset_down(struct semaphore *psem)
+{
+       if (cpuset_sem_owner != current) {
+               down(psem);
+               cpuset_sem_owner = current;
+       }
+       cpuset_sem_depth++;
+}
+
+static inline void cpuset_up(struct semaphore *psem)
+{
+       if (--cpuset_sem_depth == 0) {
+               cpuset_sem_owner = NULL;
+               up(psem);
+       }
+}
 
 /*
  * A couple of forward declarations required, due to cyclic reference loop:
@@ -522,19 +558,10 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
  * Refresh current tasks mems_allowed and mems_generation from
  * current tasks cpuset.  Call with cpuset_sem held.
  *
- * Be sure to call refresh_mems() on any cpuset operation which
- * (1) holds cpuset_sem, and (2) might possibly alloc memory.
- * Call after obtaining cpuset_sem lock, before any possible
- * allocation.  Otherwise one risks trying to allocate memory
- * while the task cpuset_mems_generation is not the same as
- * the mems_generation in its cpuset, which would deadlock on
- * cpuset_sem in cpuset_update_current_mems_allowed().
- *
- * Since we hold cpuset_sem, once refresh_mems() is called, the
- * test (current->cpuset_mems_generation != cs->mems_generation)
- * in cpuset_update_current_mems_allowed() will remain false,
- * until we drop cpuset_sem.  Anyone else who would change our
- * cpusets mems_generation needs to lock cpuset_sem first.
+ * This routine is needed to update the per-task mems_allowed
+ * data, within the tasks context, when it is trying to allocate
+ * memory (in various mm/mempolicy.c routines) and notices
+ * that some other task has been modifying its cpuset.
  */
 
 static void refresh_mems(void)
@@ -840,7 +867,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
        }
        buffer[nbytes] = 0;     /* nul-terminate */
 
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
 
        if (is_removed(cs)) {
                retval = -ENODEV;
@@ -874,7 +901,7 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
        if (retval == 0)
                retval = nbytes;
 out2:
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
        cpuset_release_agent(pathbuf);
 out1:
        kfree(buffer);
@@ -914,9 +941,9 @@ static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
 {
        cpumask_t mask;
 
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
        mask = cs->cpus_allowed;
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
 
        return cpulist_scnprintf(page, PAGE_SIZE, mask);
 }
@@ -925,9 +952,9 @@ static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
 {
        nodemask_t mask;
 
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
        mask = cs->mems_allowed;
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
 
        return nodelist_scnprintf(page, PAGE_SIZE, mask);
 }
@@ -972,6 +999,10 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
        *s++ = '\n';
        *s = '\0';
 
+       /* Do nothing if *ppos is at the eof or beyond the eof. */
+       if (s - page <= *ppos)
+               return 0;
+
        start = page + *ppos;
        n = s - start;
        retval = n - copy_to_user(buf, start, min(n, nbytes));
@@ -1330,8 +1361,7 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
        if (!cs)
                return -ENOMEM;
 
-       down(&cpuset_sem);
-       refresh_mems();
+       cpuset_down(&cpuset_sem);
        cs->flags = 0;
        if (notify_on_release(parent))
                set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
@@ -1356,14 +1386,14 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
         * will down() this new directory's i_sem and if we race with
         * another mkdir, we might deadlock.
         */
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
 
        err = cpuset_populate_dir(cs->dentry);
        /* If err < 0, we have a half-filled directory - oh well ;) */
        return 0;
 err:
        list_del(&cs->sibling);
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
        kfree(cs);
        return err;
 }
@@ -1385,14 +1415,13 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
 
        /* the vfs holds both inode->i_sem already */
 
-       down(&cpuset_sem);
-       refresh_mems();
+       cpuset_down(&cpuset_sem);
        if (atomic_read(&cs->count) > 0) {
-               up(&cpuset_sem);
+               cpuset_up(&cpuset_sem);
                return -EBUSY;
        }
        if (!list_empty(&cs->children)) {
-               up(&cpuset_sem);
+               cpuset_up(&cpuset_sem);
                return -EBUSY;
        }
        parent = cs->parent;
@@ -1408,7 +1437,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
        spin_unlock(&d->d_lock);
        cpuset_d_remove_dir(d);
        dput(d);
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
        cpuset_release_agent(pathbuf);
        return 0;
 }
@@ -1511,10 +1540,10 @@ void cpuset_exit(struct task_struct *tsk)
        if (notify_on_release(cs)) {
                char *pathbuf = NULL;
 
-               down(&cpuset_sem);
+               cpuset_down(&cpuset_sem);
                if (atomic_dec_and_test(&cs->count))
                        check_for_release(cs, &pathbuf);
-               up(&cpuset_sem);
+               cpuset_up(&cpuset_sem);
                cpuset_release_agent(pathbuf);
        } else {
                atomic_dec(&cs->count);
@@ -1535,11 +1564,11 @@ cpumask_t cpuset_cpus_allowed(const struct task_struct *tsk)
 {
        cpumask_t mask;
 
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
        task_lock((struct task_struct *)tsk);
        guarantee_online_cpus(tsk->cpuset, &mask);
        task_unlock((struct task_struct *)tsk);
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
 
        return mask;
 }
@@ -1564,9 +1593,9 @@ void cpuset_update_current_mems_allowed(void)
        if (!cs)
                return;         /* task is exiting */
        if (current->cpuset_mems_generation != cs->mems_generation) {
-               down(&cpuset_sem);
+               cpuset_down(&cpuset_sem);
                refresh_mems();
-               up(&cpuset_sem);
+               cpuset_up(&cpuset_sem);
        }
 }
 
@@ -1665,14 +1694,14 @@ int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask)
                return 0;
 
        /* Not hardwall and node outside mems_allowed: scan up cpusets */
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
        cs = current->cpuset;
        if (!cs)
                goto done;              /* current task exiting */
        cs = nearest_exclusive_ancestor(cs);
        allowed = node_isset(node, cs->mems_allowed);
 done:
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
        return allowed;
 }
 
@@ -1693,7 +1722,7 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p)
        const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */
        int overlap = 0;                /* do cpusets overlap? */
 
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
        cs1 = current->cpuset;
        if (!cs1)
                goto done;              /* current task exiting */
@@ -1704,7 +1733,7 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p)
        cs2 = nearest_exclusive_ancestor(cs2);
        overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
 done:
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
 
        return overlap;
 }
@@ -1727,7 +1756,7 @@ static int proc_cpuset_show(struct seq_file *m, void *v)
                return -ENOMEM;
 
        tsk = m->private;
-       down(&cpuset_sem);
+       cpuset_down(&cpuset_sem);
        task_lock(tsk);
        cs = tsk->cpuset;
        task_unlock(tsk);
@@ -1742,7 +1771,7 @@ static int proc_cpuset_show(struct seq_file *m, void *v)
        seq_puts(m, buf);
        seq_putc(m, '\n');
 out:
-       up(&cpuset_sem);
+       cpuset_up(&cpuset_sem);
        kfree(buf);
        return retval;
 }
index 5b0fb9f09f212d05642dd343be2692a2b0a039b7..6d2089a1bce74614009acfb18f1e3b95458e90cf 100644 (file)
@@ -368,17 +368,19 @@ EXPORT_SYMBOL(daemonize);
 static inline void close_files(struct files_struct * files)
 {
        int i, j;
+       struct fdtable *fdt;
 
        j = 0;
+       fdt = files_fdtable(files);
        for (;;) {
                unsigned long set;
                i = j * __NFDBITS;
-               if (i >= files->max_fdset || i >= files->max_fds)
+               if (i >= fdt->max_fdset || i >= fdt->max_fds)
                        break;
-               set = files->open_fds->fds_bits[j++];
+               set = fdt->open_fds->fds_bits[j++];
                while (set) {
                        if (set & 1) {
-                               struct file * file = xchg(&files->fd[i], NULL);
+                               struct file * file = xchg(&fdt->fd[i], NULL);
                                if (file)
                                        filp_close(file, files);
                        }
@@ -403,18 +405,22 @@ struct files_struct *get_files_struct(struct task_struct *task)
 
 void fastcall put_files_struct(struct files_struct *files)
 {
+       struct fdtable *fdt;
+
        if (atomic_dec_and_test(&files->count)) {
                close_files(files);
                /*
                 * Free the fd and fdset arrays if we expanded them.
+                * If the fdtable was embedded, pass files for freeing
+                * at the end of the RCU grace period. Otherwise,
+                * you can free files immediately.
                 */
-               if (files->fd != &files->fd_array[0])
-                       free_fd_array(files->fd, files->max_fds);
-               if (files->max_fdset > __FD_SETSIZE) {
-                       free_fdset(files->open_fds, files->max_fdset);
-                       free_fdset(files->close_on_exec, files->max_fdset);
-               }
-               kmem_cache_free(files_cachep, files);
+               fdt = files_fdtable(files);
+               if (fdt == &files->fdtab)
+                       fdt->free_files = files;
+               else
+                       kmem_cache_free(files_cachep, files);
+               free_fdtable(fdt);
        }
 }
 
index 7e1ead9a6ba453bbfafab739df3690e69684e769..8149f3602881db80727310245436c97a661adf2a 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/syscalls.h>
 #include <linux/jiffies.h>
 #include <linux/futex.h>
+#include <linux/rcupdate.h>
 #include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
@@ -176,6 +177,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        /* One for us, one for whoever does the "release_task()" (usually parent) */
        atomic_set(&tsk->usage,2);
+       atomic_set(&tsk->fs_excl, 0);
        return tsk;
 }
 
@@ -564,24 +566,53 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
        return 0;
 }
 
-static int count_open_files(struct files_struct *files, int size)
+static int count_open_files(struct fdtable *fdt)
 {
+       int size = fdt->max_fdset;
        int i;
 
        /* Find the last open fd */
        for (i = size/(8*sizeof(long)); i > 0; ) {
-               if (files->open_fds->fds_bits[--i])
+               if (fdt->open_fds->fds_bits[--i])
                        break;
        }
        i = (i+1) * 8 * sizeof(long);
        return i;
 }
 
+static struct files_struct *alloc_files(void)
+{
+       struct files_struct *newf;
+       struct fdtable *fdt;
+
+       newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
+       if (!newf)
+               goto out;
+
+       atomic_set(&newf->count, 1);
+
+       spin_lock_init(&newf->file_lock);
+       fdt = &newf->fdtab;
+       fdt->next_fd = 0;
+       fdt->max_fds = NR_OPEN_DEFAULT;
+       fdt->max_fdset = __FD_SETSIZE;
+       fdt->close_on_exec = &newf->close_on_exec_init;
+       fdt->open_fds = &newf->open_fds_init;
+       fdt->fd = &newf->fd_array[0];
+       INIT_RCU_HEAD(&fdt->rcu);
+       fdt->free_files = NULL;
+       fdt->next = NULL;
+       rcu_assign_pointer(newf->fdt, fdt);
+out:
+       return newf;
+}
+
 static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
 {
        struct files_struct *oldf, *newf;
        struct file **old_fds, **new_fds;
        int open_files, size, i, error = 0, expand;
+       struct fdtable *old_fdt, *new_fdt;
 
        /*
         * A background process may not have any files ...
@@ -602,35 +633,27 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
         */
        tsk->files = NULL;
        error = -ENOMEM;
-       newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
-       if (!newf) 
+       newf = alloc_files();
+       if (!newf)
                goto out;
 
-       atomic_set(&newf->count, 1);
-
-       spin_lock_init(&newf->file_lock);
-       newf->next_fd       = 0;
-       newf->max_fds       = NR_OPEN_DEFAULT;
-       newf->max_fdset     = __FD_SETSIZE;
-       newf->close_on_exec = &newf->close_on_exec_init;
-       newf->open_fds      = &newf->open_fds_init;
-       newf->fd            = &newf->fd_array[0];
-
        spin_lock(&oldf->file_lock);
-
-       open_files = count_open_files(oldf, oldf->max_fdset);
+       old_fdt = files_fdtable(oldf);
+       new_fdt = files_fdtable(newf);
+       size = old_fdt->max_fdset;
+       open_files = count_open_files(old_fdt);
        expand = 0;
 
        /*
         * Check whether we need to allocate a larger fd array or fd set.
         * Note: we're not a clone task, so the open count won't  change.
         */
-       if (open_files > newf->max_fdset) {
-               newf->max_fdset = 0;
+       if (open_files > new_fdt->max_fdset) {
+               new_fdt->max_fdset = 0;
                expand = 1;
        }
-       if (open_files > newf->max_fds) {
-               newf->max_fds = 0;
+       if (open_files > new_fdt->max_fds) {
+               new_fdt->max_fds = 0;
                expand = 1;
        }
 
@@ -642,14 +665,21 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
                spin_unlock(&newf->file_lock);
                if (error < 0)
                        goto out_release;
+               new_fdt = files_fdtable(newf);
+               /*
+                * Reacquire the oldf lock and a pointer to its fd table
+                * who knows it may have a new bigger fd table. We need
+                * the latest pointer.
+                */
                spin_lock(&oldf->file_lock);
+               old_fdt = files_fdtable(oldf);
        }
 
-       old_fds = oldf->fd;
-       new_fds = newf->fd;
+       old_fds = old_fdt->fd;
+       new_fds = new_fdt->fd;
 
-       memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8);
-       memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8);
+       memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8);
+       memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8);
 
        for (i = open_files; i != 0; i--) {
                struct file *f = *old_fds++;
@@ -662,24 +692,24 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
                         * is partway through open().  So make sure that this
                         * fd is available to the new process.
                         */
-                       FD_CLR(open_files - i, newf->open_fds);
+                       FD_CLR(open_files - i, new_fdt->open_fds);
                }
-               *new_fds++ = f;
+               rcu_assign_pointer(*new_fds++, f);
        }
        spin_unlock(&oldf->file_lock);
 
        /* compute the remainder to be cleared */
-       size = (newf->max_fds - open_files) * sizeof(struct file *);
+       size = (new_fdt->max_fds - open_files) * sizeof(struct file *);
 
        /* This is long word aligned thus could use a optimized version */ 
        memset(new_fds, 0, size); 
 
-       if (newf->max_fdset > open_files) {
-               int left = (newf->max_fdset-open_files)/8;
+       if (new_fdt->max_fdset > open_files) {
+               int left = (new_fdt->max_fdset-open_files)/8;
                int start = open_files / (8 * sizeof(unsigned long));
 
-               memset(&newf->open_fds->fds_bits[start], 0, left);
-               memset(&newf->close_on_exec->fds_bits[start], 0, left);
+               memset(&new_fdt->open_fds->fds_bits[start], 0, left);
+               memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
        }
 
        tsk->files = newf;
@@ -688,9 +718,9 @@ out:
        return error;
 
 out_release:
-       free_fdset (newf->close_on_exec, newf->max_fdset);
-       free_fdset (newf->open_fds, newf->max_fdset);
-       free_fd_array(newf->fd, newf->max_fds);
+       free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
+       free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
+       free_fd_array(new_fdt->fd, new_fdt->max_fds);
        kmem_cache_free(files_cachep, newf);
        goto out;
 }
@@ -1115,6 +1145,9 @@ static task_t *copy_process(unsigned long clone_flags,
                        __get_cpu_var(process_counts)++;
        }
 
+       if (!current->signal->tty && p->signal->tty)
+               p->signal->tty = NULL;
+
        nr_threads++;
        total_forks++;
        write_unlock_irq(&tasklist_lock);
index f436993bd590a4b0bb145d4402d52cb2aaeb7c76..bef3b6901b7693e11ce2ddd0fa2ee4c1c00c566d 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/percpu.h>
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
+#include <linux/rcuref.h>
 #include <linux/cpu.h>
 
 /* Definition for rcupdate control block. */
@@ -72,6 +73,19 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
 static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
 static int maxbatch = 10;
 
+#ifndef __HAVE_ARCH_CMPXCHG
+/*
+ * We use an array of spinlocks for the rcurefs -- similar to ones in sparc
+ * 32 bit atomic_t implementations, and a hash function similar to that
+ * for our refcounting needs.
+ * Can't help multiprocessors which donot have cmpxchg :(
+ */
+
+spinlock_t __rcuref_hash[RCUREF_HASH_SIZE] = {
+       [0 ... (RCUREF_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+};
+#endif
+
 /**
  * call_rcu - Queue an RCU callback for invocation after a grace period.
  * @head: structure to be used for queueing the RCU updates.
index 18b95520a2e29bdfa181aecb913f0ea50995f609..81b3a96ed2d09a79f7937503a88c3ced4c959953 100644 (file)
@@ -875,7 +875,7 @@ static int migrate_task(task_t *p, int dest_cpu, migration_req_t *req)
  * smp_call_function() if an IPI is sent by the same process we are
  * waiting to become inactive.
  */
-void wait_task_inactive(task_t * p)
+void wait_task_inactive(task_t *p)
 {
        unsigned long flags;
        runqueue_t *rq;
@@ -966,8 +966,11 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
                int local_group;
                int i;
 
+               /* Skip over this group if it has no CPUs allowed */
+               if (!cpus_intersects(group->cpumask, p->cpus_allowed))
+                       goto nextgroup;
+
                local_group = cpu_isset(this_cpu, group->cpumask);
-               /* XXX: put a cpus allowed check */
 
                /* Tally up the load of all CPUs in the group */
                avg_load = 0;
@@ -992,6 +995,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
                        min_load = avg_load;
                        idlest = group;
                }
+nextgroup:
                group = group->next;
        } while (group != sd->groups);
 
@@ -1003,13 +1007,18 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
 /*
  * find_idlest_queue - find the idlest runqueue among the cpus in group.
  */
-static int find_idlest_cpu(struct sched_group *group, int this_cpu)
+static int
+find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
 {
+       cpumask_t tmp;
        unsigned long load, min_load = ULONG_MAX;
        int idlest = -1;
        int i;
 
-       for_each_cpu_mask(i, group->cpumask) {
+       /* Traverse only the allowed CPUs */
+       cpus_and(tmp, group->cpumask, p->cpus_allowed);
+
+       for_each_cpu_mask(i, tmp) {
                load = source_load(i, 0);
 
                if (load < min_load || (load == min_load && i == this_cpu)) {
@@ -1052,7 +1061,7 @@ static int sched_balance_self(int cpu, int flag)
                if (!group)
                        goto nextlevel;
 
-               new_cpu = find_idlest_cpu(group, cpu);
+               new_cpu = find_idlest_cpu(group, t, cpu);
                if (new_cpu == -1 || new_cpu == cpu)
                        goto nextlevel;
 
@@ -1127,7 +1136,7 @@ static inline int wake_idle(int cpu, task_t *p)
  *
  * returns failure only if the task is already active.
  */
-static int try_to_wake_up(task_t * p, unsigned int state, int sync)
+static int try_to_wake_up(task_t *p, unsigned int state, int sync)
 {
        int cpu, this_cpu, success = 0;
        unsigned long flags;
@@ -1251,6 +1260,16 @@ out_activate:
                p->activated = -1;
        }
 
+       /*
+        * Tasks that have marked their sleep as noninteractive get
+        * woken up without updating their sleep average. (i.e. their
+        * sleep is handled in a priority-neutral manner, no priority
+        * boost and no penalty.)
+        */
+       if (old_state & TASK_NONINTERACTIVE)
+               __activate_task(p, rq);
+       else
+               activate_task(p, rq, cpu == this_cpu);
        /*
         * Sync wakeups (i.e. those types of wakeups where the waker
         * has indicated that it will leave the CPU in short order)
@@ -1259,7 +1278,6 @@ out_activate:
         * the waker guarantees that the freshly woken up task is going
         * to be considered on this CPU.)
         */
-       activate_task(p, rq, cpu == this_cpu);
        if (!sync || cpu != this_cpu) {
                if (TASK_PREEMPTS_CURR(p, rq))
                        resched_task(rq->curr);
@@ -1274,7 +1292,7 @@ out:
        return success;
 }
 
-int fastcall wake_up_process(task_t * p)
+int fastcall wake_up_process(task_t *p)
 {
        return try_to_wake_up(p, TASK_STOPPED | TASK_TRACED |
                                 TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0);
@@ -1353,7 +1371,7 @@ void fastcall sched_fork(task_t *p, int clone_flags)
  * that must be done for every newly created context, then puts the task
  * on the runqueue and wakes it.
  */
-void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
+void fastcall wake_up_new_task(task_t *p, unsigned long clone_flags)
 {
        unsigned long flags;
        int this_cpu, cpu;
@@ -1436,7 +1454,7 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
  * artificially, because any timeslice recovered here
  * was given away by the parent in the first place.)
  */
-void fastcall sched_exit(task_t * p)
+void fastcall sched_exit(task_t *p)
 {
        unsigned long flags;
        runqueue_t *rq;
@@ -1511,6 +1529,10 @@ static inline void finish_task_switch(runqueue_t *rq, task_t *prev)
         *              Manfred Spraul <manfred@colorfullife.com>
         */
        prev_task_flags = prev->flags;
+#ifdef CONFIG_DEBUG_SPINLOCK
+       /* this is a valid case when another task releases the spinlock */
+       rq->lock.owner = current;
+#endif
        finish_arch_switch(prev);
        finish_lock_switch(rq, prev);
        if (mm)
@@ -1753,7 +1775,8 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
  */
 static inline
 int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
-            struct sched_domain *sd, enum idle_type idle, int *all_pinned)
+                    struct sched_domain *sd, enum idle_type idle,
+                    int *all_pinned)
 {
        /*
         * We do not migrate tasks that are:
@@ -1883,10 +1906,11 @@ out:
  */
 static struct sched_group *
 find_busiest_group(struct sched_domain *sd, int this_cpu,
-                  unsigned long *imbalance, enum idle_type idle)
+                  unsigned long *imbalance, enum idle_type idle, int *sd_idle)
 {
        struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
        unsigned long max_load, avg_load, total_load, this_load, total_pwr;
+       unsigned long max_pull;
        int load_idx;
 
        max_load = this_load = total_load = total_pwr = 0;
@@ -1908,6 +1932,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
                avg_load = 0;
 
                for_each_cpu_mask(i, group->cpumask) {
+                       if (*sd_idle && !idle_cpu(i))
+                               *sd_idle = 0;
+
                        /* Bias balancing toward cpus of our domain */
                        if (local_group)
                                load = target_load(i, load_idx);
@@ -1933,7 +1960,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
                group = group->next;
        } while (group != sd->groups);
 
-       if (!busiest || this_load >= max_load)
+       if (!busiest || this_load >= max_load || max_load <= SCHED_LOAD_SCALE)
                goto out_balanced;
 
        avg_load = (SCHED_LOAD_SCALE * total_load) / total_pwr;
@@ -1953,8 +1980,12 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
         * by pulling tasks to us.  Be careful of negative numbers as they'll
         * appear as very large values with unsigned longs.
         */
+
+       /* Don't want to pull so many tasks that a group would go idle */
+       max_pull = min(max_load - avg_load, max_load - SCHED_LOAD_SCALE);
+
        /* How much load to actually move to equalise the imbalance */
-       *imbalance = min((max_load - avg_load) * busiest->cpu_power,
+       *imbalance = min(max_pull * busiest->cpu_power,
                                (avg_load - this_load) * this->cpu_power)
                        / SCHED_LOAD_SCALE;
 
@@ -2051,11 +2082,14 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
        unsigned long imbalance;
        int nr_moved, all_pinned = 0;
        int active_balance = 0;
+       int sd_idle = 0;
+
+       if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER)
+               sd_idle = 1;
 
-       spin_lock(&this_rq->lock);
        schedstat_inc(sd, lb_cnt[idle]);
 
-       group = find_busiest_group(sd, this_cpu, &imbalance, idle);
+       group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle);
        if (!group) {
                schedstat_inc(sd, lb_nobusyg[idle]);
                goto out_balanced;
@@ -2079,19 +2113,16 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
                 * still unbalanced. nr_moved simply stays zero, so it is
                 * correctly treated as an imbalance.
                 */
-               double_lock_balance(this_rq, busiest);
+               double_rq_lock(this_rq, busiest);
                nr_moved = move_tasks(this_rq, this_cpu, busiest,
-                                               imbalance, sd, idle,
-                                               &all_pinned);
-               spin_unlock(&busiest->lock);
+                                       imbalance, sd, idle, &all_pinned);
+               double_rq_unlock(this_rq, busiest);
 
                /* All tasks on this runqueue were pinned by CPU affinity */
                if (unlikely(all_pinned))
                        goto out_balanced;
        }
 
-       spin_unlock(&this_rq->lock);
-
        if (!nr_moved) {
                schedstat_inc(sd, lb_failed[idle]);
                sd->nr_balance_failed++;
@@ -2099,6 +2130,16 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
                if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
 
                        spin_lock(&busiest->lock);
+
+                       /* don't kick the migration_thread, if the curr
+                        * task on busiest cpu can't be moved to this_cpu
+                        */
+                       if (!cpu_isset(this_cpu, busiest->curr->cpus_allowed)) {
+                               spin_unlock(&busiest->lock);
+                               all_pinned = 1;
+                               goto out_one_pinned;
+                       }
+
                        if (!busiest->active_balance) {
                                busiest->active_balance = 1;
                                busiest->push_cpu = this_cpu;
@@ -2131,19 +2172,23 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
                        sd->balance_interval *= 2;
        }
 
+       if (!nr_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+               return -1;
        return nr_moved;
 
 out_balanced:
-       spin_unlock(&this_rq->lock);
-
        schedstat_inc(sd, lb_balanced[idle]);
 
        sd->nr_balance_failed = 0;
+
+out_one_pinned:
        /* tune up the balancing interval */
        if ((all_pinned && sd->balance_interval < MAX_PINNED_INTERVAL) ||
                        (sd->balance_interval < sd->max_interval))
                sd->balance_interval *= 2;
 
+       if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+               return -1;
        return 0;
 }
 
@@ -2161,9 +2206,13 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
        runqueue_t *busiest = NULL;
        unsigned long imbalance;
        int nr_moved = 0;
+       int sd_idle = 0;
+
+       if (sd->flags & SD_SHARE_CPUPOWER)
+               sd_idle = 1;
 
        schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
-       group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
+       group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE, &sd_idle);
        if (!group) {
                schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
                goto out_balanced;
@@ -2177,22 +2226,30 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
 
        BUG_ON(busiest == this_rq);
 
-       /* Attempt to move tasks */
-       double_lock_balance(this_rq, busiest);
-
        schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
-       nr_moved = move_tasks(this_rq, this_cpu, busiest,
+
+       nr_moved = 0;
+       if (busiest->nr_running > 1) {
+               /* Attempt to move tasks */
+               double_lock_balance(this_rq, busiest);
+               nr_moved = move_tasks(this_rq, this_cpu, busiest,
                                        imbalance, sd, NEWLY_IDLE, NULL);
-       if (!nr_moved)
+               spin_unlock(&busiest->lock);
+       }
+
+       if (!nr_moved) {
                schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
-       else
+               if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+                       return -1;
+       } else
                sd->nr_balance_failed = 0;
 
-       spin_unlock(&busiest->lock);
        return nr_moved;
 
 out_balanced:
        schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+       if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+               return -1;
        sd->nr_balance_failed = 0;
        return 0;
 }
@@ -2317,7 +2374,11 @@ static void rebalance_tick(int this_cpu, runqueue_t *this_rq,
 
                if (j - sd->last_balance >= interval) {
                        if (load_balance(this_cpu, this_rq, sd, idle)) {
-                               /* We've pulled tasks over so no longer idle */
+                               /*
+                                * We've pulled tasks over so either we're no
+                                * longer idle, or one of our SMT siblings is
+                                * not idle.
+                                */
                                idle = NOT_IDLE;
                        }
                        sd->last_balance += interval;
@@ -2576,6 +2637,13 @@ out:
 }
 
 #ifdef CONFIG_SCHED_SMT
+static inline void wakeup_busy_runqueue(runqueue_t *rq)
+{
+       /* If an SMT runqueue is sleeping due to priority reasons wake it up */
+       if (rq->curr == rq->idle && rq->nr_running)
+               resched_task(rq->idle);
+}
+
 static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
 {
        struct sched_domain *tmp, *sd = NULL;
@@ -2609,12 +2677,7 @@ static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
        for_each_cpu_mask(i, sibling_map) {
                runqueue_t *smt_rq = cpu_rq(i);
 
-               /*
-                * If an SMT sibling task is sleeping due to priority
-                * reasons wake it up now.
-                */
-               if (smt_rq->curr == smt_rq->idle && smt_rq->nr_running)
-                       resched_task(smt_rq->idle);
+               wakeup_busy_runqueue(smt_rq);
        }
 
        for_each_cpu_mask(i, sibling_map)
@@ -2625,6 +2688,16 @@ static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
         */
 }
 
+/*
+ * number of 'lost' timeslices this task wont be able to fully
+ * utilize, if another task runs on a sibling. This models the
+ * slowdown effect of other tasks running on siblings:
+ */
+static inline unsigned long smt_slice(task_t *p, struct sched_domain *sd)
+{
+       return p->time_slice * (100 - sd->per_cpu_gain) / 100;
+}
+
 static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
 {
        struct sched_domain *tmp, *sd = NULL;
@@ -2668,6 +2741,10 @@ static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
                runqueue_t *smt_rq = cpu_rq(i);
                task_t *smt_curr = smt_rq->curr;
 
+               /* Kernel threads do not participate in dependent sleeping */
+               if (!p->mm || !smt_curr->mm || rt_task(p))
+                       goto check_smt_task;
+
                /*
                 * If a user task with lower static priority than the
                 * running task on the SMT sibling is trying to schedule,
@@ -2676,21 +2753,45 @@ static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
                 * task from using an unfair proportion of the
                 * physical cpu's resources. -ck
                 */
-               if (((smt_curr->time_slice * (100 - sd->per_cpu_gain) / 100) >
-                       task_timeslice(p) || rt_task(smt_curr)) &&
-                       p->mm && smt_curr->mm && !rt_task(p))
-                               ret = 1;
+               if (rt_task(smt_curr)) {
+                       /*
+                        * With real time tasks we run non-rt tasks only
+                        * per_cpu_gain% of the time.
+                        */
+                       if ((jiffies % DEF_TIMESLICE) >
+                               (sd->per_cpu_gain * DEF_TIMESLICE / 100))
+                                       ret = 1;
+               } else
+                       if (smt_curr->static_prio < p->static_prio &&
+                               !TASK_PREEMPTS_CURR(p, smt_rq) &&
+                               smt_slice(smt_curr, sd) > task_timeslice(p))
+                                       ret = 1;
+
+check_smt_task:
+               if ((!smt_curr->mm && smt_curr != smt_rq->idle) ||
+                       rt_task(smt_curr))
+                               continue;
+               if (!p->mm) {
+                       wakeup_busy_runqueue(smt_rq);
+                       continue;
+               }
 
                /*
-                * Reschedule a lower priority task on the SMT sibling,
-                * or wake it up if it has been put to sleep for priority
-                * reasons.
+                * Reschedule a lower priority task on the SMT sibling for
+                * it to be put to sleep, or wake it up if it has been put to
+                * sleep for priority reasons to see if it should run now.
                 */
-               if ((((p->time_slice * (100 - sd->per_cpu_gain) / 100) >
-                       task_timeslice(smt_curr) || rt_task(p)) &&
-                       smt_curr->mm && p->mm && !rt_task(smt_curr)) ||
-                       (smt_curr == smt_rq->idle && smt_rq->nr_running))
-                               resched_task(smt_curr);
+               if (rt_task(p)) {
+                       if ((jiffies % DEF_TIMESLICE) >
+                               (sd->per_cpu_gain * DEF_TIMESLICE / 100))
+                                       resched_task(smt_curr);
+               } else {
+                       if (TASK_PREEMPTS_CURR(p, smt_rq) &&
+                               smt_slice(p, sd) > task_timeslice(smt_curr))
+                                       resched_task(smt_curr);
+                       else
+                               wakeup_busy_runqueue(smt_rq);
+               }
        }
 out_unlock:
        for_each_cpu_mask(i, sibling_map)
@@ -2888,6 +2989,7 @@ switch_tasks:
        if (next == rq->idle)
                schedstat_inc(rq, sched_goidle);
        prefetch(next);
+       prefetch_stack(next);
        clear_tsk_need_resched(prev);
        rcu_qsctr_inc(task_cpu(prev));
 
@@ -3015,7 +3117,8 @@ need_resched:
 
 #endif /* CONFIG_PREEMPT */
 
-int default_wake_function(wait_queue_t *curr, unsigned mode, int sync, void *key)
+int default_wake_function(wait_queue_t *curr, unsigned mode, int sync,
+                         void *key)
 {
        task_t *p = curr->private;
        return try_to_wake_up(p, mode, sync);
@@ -3057,7 +3160,7 @@ static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
  * @key: is directly passed to the wakeup function
  */
 void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
-                               int nr_exclusive, void *key)
+                       int nr_exclusive, void *key)
 {
        unsigned long flags;
 
@@ -3089,7 +3192,8 @@ void fastcall __wake_up_locked(wait_queue_head_t *q, unsigned int mode)
  *
  * On UP it can prevent extra preemption.
  */
-void fastcall __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+void fastcall
+__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
        unsigned long flags;
        int sync = 1;
@@ -3280,7 +3384,8 @@ void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
 
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long fastcall __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long fastcall __sched
+interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
        SLEEP_ON_VAR
 
@@ -3499,7 +3604,8 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
  * @policy: new policy.
  * @param: structure containing the new RT priority.
  */
-int sched_setscheduler(struct task_struct *p, int policy, struct sched_param *param)
+int sched_setscheduler(struct task_struct *p, int policy,
+                      struct sched_param *param)
 {
        int retval;
        int oldprio, oldpolicy = -1;
@@ -3519,7 +3625,7 @@ recheck:
         * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0.
         */
        if (param->sched_priority < 0 ||
-           (p->mm &&  param->sched_priority > MAX_USER_RT_PRIO-1) ||
+           (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
            (!p->mm && param->sched_priority > MAX_RT_PRIO-1))
                return -EINVAL;
        if ((policy == SCHED_NORMAL) != (param->sched_priority == 0))
@@ -3582,7 +3688,8 @@ recheck:
 }
 EXPORT_SYMBOL_GPL(sched_setscheduler);
 
-static int do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
+static int
+do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
 {
        int retval;
        struct sched_param lparam;
@@ -3849,7 +3956,7 @@ asmlinkage long sys_sched_yield(void)
        if (rt_task(current))
                target = rq->active;
 
-       if (current->array->nr_active == 1) {
+       if (array->nr_active == 1) {
                schedstat_inc(rq, yld_act_empty);
                if (!rq->expired->nr_active)
                        schedstat_inc(rq, yld_both_empty);
@@ -3913,7 +4020,7 @@ EXPORT_SYMBOL(cond_resched);
  * operations here to prevent schedule() from being called twice (once via
  * spin_unlock(), once by hand).
  */
-int cond_resched_lock(spinlock_t * lock)
+int cond_resched_lock(spinlock_t *lock)
 {
        int ret = 0;
 
@@ -4096,7 +4203,7 @@ static inline struct task_struct *younger_sibling(struct task_struct *p)
        return list_entry(p->sibling.next,struct task_struct,sibling);
 }
 
-static void show_task(task_t * p)
+static void show_task(task_t *p)
 {
        task_t *relative;
        unsigned state;
@@ -4122,7 +4229,7 @@ static void show_task(task_t * p)
 #endif
 #ifdef CONFIG_DEBUG_STACK_USAGE
        {
-               unsigned long * n = (unsigned long *) (p->thread_info+1);
+               unsigned long *n = (unsigned long *) (p->thread_info+1);
                while (!*n)
                        n++;
                free = (unsigned long) n - (unsigned long)(p->thread_info+1);
@@ -4331,7 +4438,7 @@ out:
  * thread migration by bumping thread off CPU then 'pushing' onto
  * another runqueue.
  */
-static int migration_thread(void * data)
+static int migration_thread(void *data)
 {
        runqueue_t *rq;
        int cpu = (long)data;
@@ -5495,3 +5602,47 @@ void normalize_rt_tasks(void)
 }
 
 #endif /* CONFIG_MAGIC_SYSRQ */
+
+#ifdef CONFIG_IA64
+/*
+ * These functions are only useful for the IA64 MCA handling.
+ *
+ * They can only be called when the whole system has been
+ * stopped - every CPU needs to be quiescent, and no scheduling
+ * activity can take place. Using them for anything else would
+ * be a serious bug, and as a result, they aren't even visible
+ * under any other configuration.
+ */
+
+/**
+ * curr_task - return the current task for a given cpu.
+ * @cpu: the processor in question.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+task_t *curr_task(int cpu)
+{
+       return cpu_curr(cpu);
+}
+
+/**
+ * set_curr_task - set the current task for a given cpu.
+ * @cpu: the processor in question.
+ * @p: the task pointer to set.
+ *
+ * Description: This function must only be used when non-maskable interrupts
+ * are serviced on a separate stack.  It allows the architecture to switch the
+ * notion of the current task on a cpu in a non-blocking manner.  This function
+ * must be called with all CPU's synchronized, and interrupts disabled, the
+ * and caller must save the original value of the current task (see
+ * curr_task() above) and restore that value before reenabling interrupts and
+ * re-starting the system.
+ *
+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
+ */
+void set_curr_task(int cpu, task_t *p)
+{
+       cpu_curr(cpu) = p;
+}
+
+#endif
index 4980a073237ff45ed28c39b38225c40923da0848..b92c3c9f8b9a24529e18eb2a1a1bf75f87840f10 100644 (file)
@@ -2221,8 +2221,7 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese,
                        recalc_sigpending();
                        spin_unlock_irq(&current->sighand->siglock);
 
-                       current->state = TASK_INTERRUPTIBLE;
-                       timeout = schedule_timeout(timeout);
+                       timeout = schedule_timeout_interruptible(timeout);
 
                        try_to_freeze();
                        spin_lock_irq(&current->sighand->siglock);
index b4ab6af1dea8513147c19694a8eff8a4353c69e0..f766b2fc48be8cd54cc254c91660ec414603a2c5 100644 (file)
@@ -84,7 +84,7 @@ asmlinkage void __do_softirq(void)
        cpu = smp_processor_id();
 restart:
        /* Reset the pending bitmask before enabling irqs */
-       local_softirq_pending() = 0;
+       set_softirq_pending(0);
 
        local_irq_enable();
 
index 0c3f9d8bbe17b3bd00a1c4a77e941bbebc90e226..0375fcd5921df5fe390ec6a3f1c1ce402d240f80 100644 (file)
@@ -3,7 +3,10 @@
  *
  * Author: Zwane Mwaikambo <zwane@fsmlabs.com>
  *
- * Copyright (2004) Ingo Molnar
+ * Copyright (2004, 2005) Ingo Molnar
+ *
+ * This file contains the spinlock/rwlock implementations for the
+ * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them)
  */
 
 #include <linux/config.h>
  * Generic declaration of the raw read_trylock() function,
  * architectures are supposed to optimize this:
  */
-int __lockfunc generic_raw_read_trylock(rwlock_t *lock)
+int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock)
 {
-       _raw_read_lock(lock);
+       __raw_read_lock(lock);
        return 1;
 }
-EXPORT_SYMBOL(generic_raw_read_trylock);
+EXPORT_SYMBOL(generic__raw_read_trylock);
 
 int __lockfunc _spin_trylock(spinlock_t *lock)
 {
@@ -57,7 +60,7 @@ int __lockfunc _write_trylock(rwlock_t *lock)
 }
 EXPORT_SYMBOL(_write_trylock);
 
-#ifndef CONFIG_PREEMPT
+#if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP)
 
 void __lockfunc _read_lock(rwlock_t *lock)
 {
@@ -72,7 +75,7 @@ unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
 
        local_irq_save(flags);
        preempt_disable();
-       _raw_spin_lock_flags(lock, flags);
+       _raw_spin_lock_flags(lock, &flags);
        return flags;
 }
 EXPORT_SYMBOL(_spin_lock_irqsave);
index 13e2b513be019bf0b8b6b9218e4f268fff95f58a..f4152fcd9f8effecb04229c6e3a239576e7e09af 100644 (file)
@@ -1154,6 +1154,20 @@ fastcall signed long __sched schedule_timeout(signed long timeout)
 
 EXPORT_SYMBOL(schedule_timeout);
 
+signed long __sched schedule_timeout_interruptible(signed long timeout)
+{
+       set_current_state(TASK_INTERRUPTIBLE);
+       return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_interruptible);
+
+signed long __sched schedule_timeout_uninterruptible(signed long timeout)
+{
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_uninterruptible);
+
 /* Thread ID - the internal kernel "pid" */
 asmlinkage long sys_gettid(void)
 {
@@ -1170,8 +1184,7 @@ static long __sched nanosleep_restart(struct restart_block *restart)
        if (!time_after(expire, now))
                return 0;
 
-       current->state = TASK_INTERRUPTIBLE;
-       expire = schedule_timeout(expire - now);
+       expire = schedule_timeout_interruptible(expire - now);
 
        ret = 0;
        if (expire) {
@@ -1199,8 +1212,7 @@ asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __us
                return -EINVAL;
 
        expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
-       current->state = TASK_INTERRUPTIBLE;
-       expire = schedule_timeout(expire);
+       expire = schedule_timeout_interruptible(expire);
 
        ret = 0;
        if (expire) {
@@ -1598,10 +1610,8 @@ void msleep(unsigned int msecs)
 {
        unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
-       while (timeout) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-       }
+       while (timeout)
+               timeout = schedule_timeout_uninterruptible(timeout);
 }
 
 EXPORT_SYMBOL(msleep);
@@ -1614,10 +1624,8 @@ unsigned long msleep_interruptible(unsigned int msecs)
 {
        unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
-       while (timeout && !signal_pending(current)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-       }
+       while (timeout && !signal_pending(current))
+               timeout = schedule_timeout_interruptible(timeout);
        return jiffies_to_msecs(timeout);
 }
 
index 3754c9a8f5c8e1e3fccebf2d0f282fd5eda6bcb4..016e89a44ac8defe6c753bd73d6bc74aa4e48e0f 100644 (file)
@@ -170,11 +170,11 @@ config DEBUG_FS
 
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
-       depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
+       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML)
        default y if DEBUG_INFO && UML
        help
          If you say Y here the resulting kernel image will be slightly larger
-         and slower, but it will give very useful debugging information.
-         If you don't debug the kernel, you can say N, but we may not be able
-         to solve problems without frame pointers.
+         and slower, but it might give very useful debugging information
+         on some architectures or you use external debuggers.
+         If you don't debug the kernel, you can say N.
 
index d9c38ba05e7bc2fcb3cbbca915bf43c51bd580fd..44a46750690ae3af65f338eefb2635ee4f9b70f5 100644 (file)
@@ -16,6 +16,7 @@ CFLAGS_kobject.o += -DDEBUG
 CFLAGS_kobject_uevent.o += -DDEBUG
 endif
 
+obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
index 6658d81e1836517107b5b8b39aa0c7e65032ec6e..2377af057d099ebd628bd9f7039cd4f54c9bf229 100644 (file)
@@ -25,8 +25,6 @@
  * this is trivially done efficiently using a load-locked
  * store-conditional approach, for example.
  */
-
-#ifndef ATOMIC_DEC_AND_LOCK
 int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 {
        spin_lock(lock);
@@ -37,4 +35,3 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
 }
 
 EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
index bd2bc5d887b815e261ff82c4167e410966b659d3..cb5490ec00f20f4fea3640275192f20d942a7fba 100644 (file)
@@ -177,8 +177,7 @@ static inline void __lock_kernel(void)
 
 static inline void __unlock_kernel(void)
 {
-       _raw_spin_unlock(&kernel_flag);
-       preempt_enable();
+       spin_unlock(&kernel_flag);
 }
 
 /*
index b972dd29289d6669fd353dcd2b3118cd93ab87cb..6a8bc6e06431eec49c1af2f34ec42d7d100e4e0b 100644 (file)
@@ -110,7 +110,7 @@ radix_tree_node_free(struct radix_tree_node *node)
  * success, return zero, with preemption disabled.  On error, return -ENOMEM
  * with preemption not disabled.
  */
-int radix_tree_preload(int gfp_mask)
+int radix_tree_preload(unsigned int __nocast gfp_mask)
 {
        struct radix_tree_preload *rtp;
        struct radix_tree_node *node;
index b73dbb0e7c83a4721fafbe4401c551a02e3225f9..ddc4d35df289cff02a996ba41d0d560ce9ccdead 100644 (file)
@@ -6,15 +6,16 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/sort.h>
 
-void u32_swap(void *a, void *b, int size)
+static void u32_swap(void *a, void *b, int size)
 {
        u32 t = *(u32 *)a;
        *(u32 *)a = *(u32 *)b;
        *(u32 *)b = t;
 }
 
-void generic_swap(void *a, void *b, int size)
+static void generic_swap(void *a, void *b, int size)
 {
        char t;
 
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
new file mode 100644 (file)
index 0000000..906ad10
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2005, Red Hat, Inc., Ingo Molnar
+ * Released under the General Public License (GPL).
+ *
+ * This file contains the spinlock/rwlock implementations for
+ * DEBUG_SPINLOCK.
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+static void spin_bug(spinlock_t *lock, const char *msg)
+{
+       static long print_once = 1;
+       struct task_struct *owner = NULL;
+
+       if (xchg(&print_once, 0)) {
+               if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
+                       owner = lock->owner;
+               printk("BUG: spinlock %s on CPU#%d, %s/%d\n",
+                       msg, smp_processor_id(), current->comm, current->pid);
+               printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n",
+                       lock, lock->magic,
+                       owner ? owner->comm : "<none>",
+                       owner ? owner->pid : -1,
+                       lock->owner_cpu);
+               dump_stack();
+#ifdef CONFIG_SMP
+               /*
+                * We cannot continue on SMP:
+                */
+//             panic("bad locking");
+#endif
+       }
+}
+
+#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
+
+static inline void debug_spin_lock_before(spinlock_t *lock)
+{
+       SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
+       SPIN_BUG_ON(lock->owner == current, lock, "recursion");
+       SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+                                                       lock, "cpu recursion");
+}
+
+static inline void debug_spin_lock_after(spinlock_t *lock)
+{
+       lock->owner_cpu = raw_smp_processor_id();
+       lock->owner = current;
+}
+
+static inline void debug_spin_unlock(spinlock_t *lock)
+{
+       SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
+       SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked");
+       SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
+       SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
+                                                       lock, "wrong CPU");
+       lock->owner = SPINLOCK_OWNER_INIT;
+       lock->owner_cpu = -1;
+}
+
+static void __spin_lock_debug(spinlock_t *lock)
+{
+       int print_once = 1;
+       u64 i;
+
+       for (;;) {
+               for (i = 0; i < loops_per_jiffy * HZ; i++) {
+                       cpu_relax();
+                       if (__raw_spin_trylock(&lock->raw_lock))
+                               return;
+               }
+               /* lockup suspected: */
+               if (print_once) {
+                       print_once = 0;
+                       printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n",
+                               smp_processor_id(), current->comm, current->pid,
+                                       lock);
+                       dump_stack();
+               }
+       }
+}
+
+void _raw_spin_lock(spinlock_t *lock)
+{
+       debug_spin_lock_before(lock);
+       if (unlikely(!__raw_spin_trylock(&lock->raw_lock)))
+               __spin_lock_debug(lock);
+       debug_spin_lock_after(lock);
+}
+
+int _raw_spin_trylock(spinlock_t *lock)
+{
+       int ret = __raw_spin_trylock(&lock->raw_lock);
+
+       if (ret)
+               debug_spin_lock_after(lock);
+#ifndef CONFIG_SMP
+       /*
+        * Must not happen on UP:
+        */
+       SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+       return ret;
+}
+
+void _raw_spin_unlock(spinlock_t *lock)
+{
+       debug_spin_unlock(lock);
+       __raw_spin_unlock(&lock->raw_lock);
+}
+
+static void rwlock_bug(rwlock_t *lock, const char *msg)
+{
+       static long print_once = 1;
+
+       if (xchg(&print_once, 0)) {
+               printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg,
+                       smp_processor_id(), current->comm, current->pid, lock);
+               dump_stack();
+#ifdef CONFIG_SMP
+               /*
+                * We cannot continue on SMP:
+                */
+               panic("bad locking");
+#endif
+       }
+}
+
+#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
+
+static void __read_lock_debug(rwlock_t *lock)
+{
+       int print_once = 1;
+       u64 i;
+
+       for (;;) {
+               for (i = 0; i < loops_per_jiffy * HZ; i++) {
+                       cpu_relax();
+                       if (__raw_read_trylock(&lock->raw_lock))
+                               return;
+               }
+               /* lockup suspected: */
+               if (print_once) {
+                       print_once = 0;
+                       printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n",
+                               smp_processor_id(), current->comm, current->pid,
+                                       lock);
+                       dump_stack();
+               }
+       }
+}
+
+void _raw_read_lock(rwlock_t *lock)
+{
+       RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+       if (unlikely(!__raw_read_trylock(&lock->raw_lock)))
+               __read_lock_debug(lock);
+}
+
+int _raw_read_trylock(rwlock_t *lock)
+{
+       int ret = __raw_read_trylock(&lock->raw_lock);
+
+#ifndef CONFIG_SMP
+       /*
+        * Must not happen on UP:
+        */
+       RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+       return ret;
+}
+
+void _raw_read_unlock(rwlock_t *lock)
+{
+       RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+       __raw_read_unlock(&lock->raw_lock);
+}
+
+static inline void debug_write_lock_before(rwlock_t *lock)
+{
+       RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+       RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
+       RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+                                                       lock, "cpu recursion");
+}
+
+static inline void debug_write_lock_after(rwlock_t *lock)
+{
+       lock->owner_cpu = raw_smp_processor_id();
+       lock->owner = current;
+}
+
+static inline void debug_write_unlock(rwlock_t *lock)
+{
+       RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
+       RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
+       RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
+                                                       lock, "wrong CPU");
+       lock->owner = SPINLOCK_OWNER_INIT;
+       lock->owner_cpu = -1;
+}
+
+static void __write_lock_debug(rwlock_t *lock)
+{
+       int print_once = 1;
+       u64 i;
+
+       for (;;) {
+               for (i = 0; i < loops_per_jiffy * HZ; i++) {
+                       cpu_relax();
+                       if (__raw_write_trylock(&lock->raw_lock))
+                               return;
+               }
+               /* lockup suspected: */
+               if (print_once) {
+                       print_once = 0;
+                       printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n",
+                               smp_processor_id(), current->comm, current->pid,
+                                       lock);
+                       dump_stack();
+               }
+       }
+}
+
+void _raw_write_lock(rwlock_t *lock)
+{
+       debug_write_lock_before(lock);
+       if (unlikely(!__raw_write_trylock(&lock->raw_lock)))
+               __write_lock_debug(lock);
+       debug_write_lock_after(lock);
+}
+
+int _raw_write_trylock(rwlock_t *lock)
+{
+       int ret = __raw_write_trylock(&lock->raw_lock);
+
+       if (ret)
+               debug_write_lock_after(lock);
+#ifndef CONFIG_SMP
+       /*
+        * Must not happen on UP:
+        */
+       RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
+#endif
+       return ret;
+}
+
+void _raw_write_unlock(rwlock_t *lock)
+{
+       debug_write_unlock(lock);
+       __raw_write_unlock(&lock->raw_lock);
+}
index c1330cc197835ae66bffaa2baacc032ace0020b4..8ec4e4c2a179f5fc1a8d7ddb648dad0d9f69cdbb 100644 (file)
@@ -61,9 +61,17 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
 {
        bootmem_data_t *bdata = pgdat->bdata;
        unsigned long mapsize = ((end - start)+7)/8;
-
-       pgdat->pgdat_next = pgdat_list;
-       pgdat_list = pgdat;
+       static struct pglist_data *pgdat_last;
+
+       pgdat->pgdat_next = NULL;
+       /* Add new nodes last so that bootmem always starts
+          searching in the first nodes, not the last ones */
+       if (pgdat_last)
+               pgdat_last->pgdat_next = pgdat;
+       else {
+               pgdat_list = pgdat;     
+               pgdat_last = pgdat;
+       }
 
        mapsize = ALIGN(mapsize, sizeof(long));
        bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
index 88611928e71fc928a89b5b319044d759ea5f612d..b5346576e58d252ea63224606bd2564cb2f088fa 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/mman.h>
 
+static ssize_t
+generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+       loff_t offset, unsigned long nr_segs);
+
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
  * though.
@@ -301,8 +305,9 @@ EXPORT_SYMBOL(sync_page_range);
  * as it forces O_SYNC writers to different parts of the same file
  * to be serialised right until io completion.
  */
-int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
-                       loff_t pos, size_t count)
+static int sync_page_range_nolock(struct inode *inode,
+                                 struct address_space *mapping,
+                                 loff_t pos, size_t count)
 {
        pgoff_t start = pos >> PAGE_CACHE_SHIFT;
        pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
@@ -317,7 +322,6 @@ int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
                ret = wait_on_page_writeback_range(mapping, start, end);
        return ret;
 }
-EXPORT_SYMBOL(sync_page_range_nolock);
 
 /**
  * filemap_fdatawait - walk the list of under-writeback pages of the given
@@ -2008,7 +2012,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
 }
 EXPORT_SYMBOL(generic_file_buffered_write);
 
-ssize_t
+static ssize_t
 __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t *ppos)
 {
@@ -2108,7 +2112,7 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
        return ret;
 }
 
-ssize_t
+static ssize_t
 __generic_file_write_nolock(struct file *file, const struct iovec *iov,
                                unsigned long nr_segs, loff_t *ppos)
 {
@@ -2229,7 +2233,7 @@ EXPORT_SYMBOL(generic_file_writev);
  * Called under i_sem for writes to S_ISREG files.   Returns -EIO if something
  * went wrong during pagecache shootdown.
  */
-ssize_t
+static ssize_t
 generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        loff_t offset, unsigned long nr_segs)
 {
@@ -2264,4 +2268,3 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        }
        return retval;
 }
-EXPORT_SYMBOL_GPL(generic_file_direct_IO);
index 788a628103405e955a7d28f9935be690eb6d021a..ae8161f1f4595bd4d58afa0b20ecf4419ff23e71 100644 (file)
@@ -2225,7 +2225,7 @@ void update_mem_hiwater(struct task_struct *tsk)
 #if !defined(__HAVE_ARCH_GATE_AREA)
 
 #if defined(AT_SYSINFO_EHDR)
-struct vm_area_struct gate_vma;
+static struct vm_area_struct gate_vma;
 
 static int __init gate_vma_init(void)
 {
index fd4e8df0f02df979bb2a2de5a891e35f82754a7d..064d70442895a05f9dbba0db0ecdcf72cf044e60 100644 (file)
@@ -57,6 +57,11 @@ DECLARE_RWSEM(nommu_vma_sem);
 struct vm_operations_struct generic_file_vm_ops = {
 };
 
+EXPORT_SYMBOL(vmalloc);
+EXPORT_SYMBOL(vfree);
+EXPORT_SYMBOL(vmalloc_to_page);
+EXPORT_SYMBOL(vmalloc_32);
+
 /*
  * Handle all mappings that got truncated by a "truncate()"
  * system call.
@@ -142,6 +147,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        return(i);
 }
 
+EXPORT_SYMBOL(get_user_pages);
+
 DEFINE_RWLOCK(vmlist_lock);
 struct vm_struct *vmlist;
 
@@ -852,7 +859,7 @@ unsigned long do_mmap_pgoff(struct file *file,
  error_getting_vma:
        up_write(&nommu_vma_sem);
        kfree(vml);
-       printk("Allocation of vml for %lu byte allocation from process %d failed\n",
+       printk("Allocation of vma for %lu byte allocation from process %d failed\n",
               len, current->pid);
        show_free_areas();
        return -ENOMEM;
@@ -909,7 +916,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 
        for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next)
                if ((*parent)->vma->vm_start == addr &&
-                   (*parent)->vma->vm_end == end)
+                   ((len == 0) || ((*parent)->vma->vm_end == end)))
                        goto found;
 
        printk("munmap of non-mmaped memory by process %d (%s): %p\n",
@@ -1054,7 +1061,8 @@ struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
                unsigned long to, unsigned long size, pgprot_t prot)
 {
-       return -EPERM;
+       vma->vm_start = vma->vm_pgoff << PAGE_SHIFT;
+       return 0;
 }
 
 void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
@@ -1073,9 +1081,10 @@ void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
 
 void update_mem_hiwater(struct task_struct *tsk)
 {
-       unsigned long rss = get_mm_counter(tsk->mm, rss);
+       unsigned long rss;
 
        if (likely(tsk->mm)) {
+               rss = get_mm_counter(tsk->mm, rss);
                if (tsk->mm->hiwater_rss < rss)
                        tsk->mm->hiwater_rss = rss;
                if (tsk->mm->hiwater_vm < tsk->mm->total_vm)
index 5ec8da12cfd986523bb1968ffa9f2ea0be064868..ac3bf33e53701171bcf4b5f6ba8b1817bdac60f5 100644 (file)
@@ -300,6 +300,5 @@ retry:
         * Give "p" a good chance of killing itself before we
         * retry to allocate memory.
         */
-       __set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(1);
+       schedule_timeout_interruptible(1);
 }
index a6329fa8f862da5aea02238c687e93843ba2a80e..0166ea15c9ee8d61f08ddc6e100de841e59205c7 100644 (file)
@@ -368,10 +368,8 @@ int wakeup_pdflush(long nr_pages)
 static void wb_timer_fn(unsigned long unused);
 static void laptop_timer_fn(unsigned long unused);
 
-static struct timer_list wb_timer =
-                       TIMER_INITIALIZER(wb_timer_fn, 0, 0);
-static struct timer_list laptop_mode_wb_timer =
-                       TIMER_INITIALIZER(laptop_timer_fn, 0, 0);
+static DEFINE_TIMER(wb_timer, wb_timer_fn, 0, 0);
+static DEFINE_TIMER(laptop_mode_wb_timer, laptop_timer_fn, 0, 0);
 
 /*
  * Periodic writeback of "old" data.
index 3974fd81d27c0de38a12a299e6f6b6dd2645cbf7..c5823c395f7145f2a66ef3ffd11af836c294845f 100644 (file)
@@ -335,7 +335,7 @@ static inline void free_pages_check(const char *function, struct page *page)
 /*
  * Frees a list of pages. 
  * Assumes all pages on list are in same zone, and of same order.
- * count is the number of pages to free, or 0 for all on the list.
+ * count is the number of pages to free.
  *
  * If the zone was previously in an "all pages pinned" state then look to
  * see if this freeing clears that state.
index db2c9e8d99095ace5bae8324f2387b9ebdbaf7c6..1f7aeb210c7bf4de0c845f65d9c2b2b77cfe8ef0 100644 (file)
@@ -666,6 +666,7 @@ static void shmem_delete_inode(struct inode *inode)
        struct shmem_inode_info *info = SHMEM_I(inode);
 
        if (inode->i_op->truncate == shmem_truncate) {
+               truncate_inode_pages(inode->i_mapping, 0);
                shmem_unacct_size(info->flags, inode->i_size);
                inode->i_size = 0;
                shmem_truncate(inode);
@@ -1607,6 +1608,15 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
        int error = -ENOSPC;
 
        if (inode) {
+               error = security_inode_init_security(inode, dir, NULL, NULL,
+                                                    NULL);
+               if (error) {
+                       if (error != -EOPNOTSUPP) {
+                               iput(inode);
+                               return error;
+                       }
+                       error = 0;
+               }
                if (dir->i_mode & S_ISGID) {
                        inode->i_gid = dir->i_gid;
                        if (S_ISDIR(mode))
@@ -1616,7 +1626,6 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
                dir->i_ctime = dir->i_mtime = CURRENT_TIME;
                d_instantiate(dentry, inode);
                dget(dentry); /* Extra count - pin the dentry in core */
-               error = 0;
        }
        return error;
 }
@@ -1746,6 +1755,16 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        if (!inode)
                return -ENOSPC;
 
+       error = security_inode_init_security(inode, dir, NULL, NULL,
+                                            NULL);
+       if (error) {
+               if (error != -EOPNOTSUPP) {
+                       iput(inode);
+                       return error;
+               }
+               error = 0;
+       }
+
        info = SHMEM_I(inode);
        inode->i_size = len-1;
        if (len <= (char *)inode - (char *)info) {
index d7c4443991fe8e29e16dfaffa30a1711c6844c30..9e876d6dfad97f2c4ab60a881edcb91d528c1c3c 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
  *
  *     At present, each engine can be growing a cache.  This should be blocked.
  *
+ * 15 March 2005. NUMA slab allocator.
+ *     Shai Fultheim <shai@scalex86.org>.
+ *     Shobhit Dayal <shobhit@calsoftinc.com>
+ *     Alok N Kataria <alokk@calsoftinc.com>
+ *     Christoph Lameter <christoph@lameter.com>
+ *
+ *     Modified the slab allocator to be node aware on NUMA systems.
+ *     Each node has its own list of partial, free and full slabs.
+ *     All object allocations for a node occur from node specific slab lists.
  */
 
 #include       <linux/config.h>
 #include       <linux/module.h>
 #include       <linux/rcupdate.h>
 #include       <linux/string.h>
+#include       <linux/nodemask.h>
 
 #include       <asm/uaccess.h>
 #include       <asm/cacheflush.h>
@@ -212,6 +222,7 @@ struct slab {
        void                    *s_mem;         /* including colour offset */
        unsigned int            inuse;          /* num of objs active in slab */
        kmem_bufctl_t           free;
+       unsigned short          nodeid;
 };
 
 /*
@@ -239,7 +250,6 @@ struct slab_rcu {
 /*
  * struct array_cache
  *
- * Per cpu structures
  * Purpose:
  * - LIFO ordering, to hand out cache-warm objects from _alloc
  * - reduce the number of linked list operations
@@ -254,6 +264,13 @@ struct array_cache {
        unsigned int limit;
        unsigned int batchcount;
        unsigned int touched;
+       spinlock_t lock;
+       void *entry[0];         /*
+                                * Must have this definition in here for the proper
+                                * alignment of array_cache. Also simplifies accessing
+                                * the entries.
+                                * [0] is for gcc 2.95. It should really be [].
+                                */
 };
 
 /* bootstrap: The caches do not work without cpuarrays anymore,
@@ -266,34 +283,83 @@ struct arraycache_init {
 };
 
 /*
- * The slab lists of all objects.
- * Hopefully reduce the internal fragmentation
- * NUMA: The spinlock could be moved from the kmem_cache_t
- * into this structure, too. Figure out what causes
- * fewer cross-node spinlock operations.
+ * The slab lists for all objects.
  */
 struct kmem_list3 {
        struct list_head        slabs_partial;  /* partial list first, better asm code */
        struct list_head        slabs_full;
        struct list_head        slabs_free;
        unsigned long   free_objects;
-       int             free_touched;
        unsigned long   next_reap;
-       struct array_cache      *shared;
+       int             free_touched;
+       unsigned int    free_limit;
+       spinlock_t      list_lock;
+       struct array_cache      *shared;        /* shared per node */
+       struct array_cache      **alien;        /* on other nodes */
 };
 
-#define LIST3_INIT(parent) \
-       { \
-               .slabs_full     = LIST_HEAD_INIT(parent.slabs_full), \
-               .slabs_partial  = LIST_HEAD_INIT(parent.slabs_partial), \
-               .slabs_free     = LIST_HEAD_INIT(parent.slabs_free) \
+/*
+ * Need this for bootstrapping a per node allocator.
+ */
+#define NUM_INIT_LISTS (2 * MAX_NUMNODES + 1)
+struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
+#define        CACHE_CACHE 0
+#define        SIZE_AC 1
+#define        SIZE_L3 (1 + MAX_NUMNODES)
+
+/*
+ * This function may be completely optimized away if
+ * a constant is passed to it. Mostly the same as
+ * what is in linux/slab.h except it returns an
+ * index.
+ */
+static inline int index_of(const size_t size)
+{
+       if (__builtin_constant_p(size)) {
+               int i = 0;
+
+#define CACHE(x) \
+       if (size <=x) \
+               return i; \
+       else \
+               i++;
+#include "linux/kmalloc_sizes.h"
+#undef CACHE
+               {
+                       extern void __bad_size(void);
+                       __bad_size();
+               }
        }
-#define list3_data(cachep) \
-       (&(cachep)->lists)
+       return 0;
+}
+
+#define INDEX_AC index_of(sizeof(struct arraycache_init))
+#define INDEX_L3 index_of(sizeof(struct kmem_list3))
+
+static inline void kmem_list3_init(struct kmem_list3 *parent)
+{
+       INIT_LIST_HEAD(&parent->slabs_full);
+       INIT_LIST_HEAD(&parent->slabs_partial);
+       INIT_LIST_HEAD(&parent->slabs_free);
+       parent->shared = NULL;
+       parent->alien = NULL;
+       spin_lock_init(&parent->list_lock);
+       parent->free_objects = 0;
+       parent->free_touched = 0;
+}
 
-/* NUMA: per-node */
-#define list3_data_ptr(cachep, ptr) \
-               list3_data(cachep)
+#define MAKE_LIST(cachep, listp, slab, nodeid) \
+       do {    \
+               INIT_LIST_HEAD(listp);          \
+               list_splice(&(cachep->nodelists[nodeid]->slab), listp); \
+       } while (0)
+
+#define        MAKE_ALL_LISTS(cachep, ptr, nodeid)                     \
+       do {                                    \
+       MAKE_LIST((cachep), (&(ptr)->slabs_full), slabs_full, nodeid);  \
+       MAKE_LIST((cachep), (&(ptr)->slabs_partial), slabs_partial, nodeid); \
+       MAKE_LIST((cachep), (&(ptr)->slabs_free), slabs_free, nodeid);  \
+       } while (0)
 
 /*
  * kmem_cache_t
@@ -306,13 +372,12 @@ struct kmem_cache_s {
        struct array_cache      *array[NR_CPUS];
        unsigned int            batchcount;
        unsigned int            limit;
-/* 2) touched by every alloc & free from the backend */
-       struct kmem_list3       lists;
-       /* NUMA: kmem_3list_t   *nodelists[MAX_NUMNODES] */
+       unsigned int            shared;
        unsigned int            objsize;
+/* 2) touched by every alloc & free from the backend */
+       struct kmem_list3       *nodelists[MAX_NUMNODES];
        unsigned int            flags;  /* constant flags */
        unsigned int            num;    /* # of objs per slab */
-       unsigned int            free_limit; /* upper limit of objects in the lists */
        spinlock_t              spinlock;
 
 /* 3) cache_grow/shrink */
@@ -349,6 +414,7 @@ struct kmem_cache_s {
        unsigned long           errors;
        unsigned long           max_freeable;
        unsigned long           node_allocs;
+       unsigned long           node_frees;
        atomic_t                allochit;
        atomic_t                allocmiss;
        atomic_t                freehit;
@@ -384,6 +450,7 @@ struct kmem_cache_s {
                                } while (0)
 #define        STATS_INC_ERR(x)        ((x)->errors++)
 #define        STATS_INC_NODEALLOCS(x) ((x)->node_allocs++)
+#define        STATS_INC_NODEFREES(x)  ((x)->node_frees++)
 #define        STATS_SET_FREEABLE(x, i) \
                                do { if ((x)->max_freeable < i) \
                                        (x)->max_freeable = i; \
@@ -402,6 +469,7 @@ struct kmem_cache_s {
 #define        STATS_SET_HIGH(x)       do { } while (0)
 #define        STATS_INC_ERR(x)        do { } while (0)
 #define        STATS_INC_NODEALLOCS(x) do { } while (0)
+#define        STATS_INC_NODEFREES(x)  do { } while (0)
 #define        STATS_SET_FREEABLE(x, i) \
                                do { } while (0)
 
@@ -534,9 +602,9 @@ static struct arraycache_init initarray_generic =
 
 /* internal cache of cache description objs */
 static kmem_cache_t cache_cache = {
-       .lists          = LIST3_INIT(cache_cache.lists),
        .batchcount     = 1,
        .limit          = BOOT_CPUCACHE_ENTRIES,
+       .shared         = 1,
        .objsize        = sizeof(kmem_cache_t),
        .flags          = SLAB_NO_REAP,
        .spinlock       = SPIN_LOCK_UNLOCKED,
@@ -557,7 +625,6 @@ static struct list_head cache_chain;
  * SLAB_RECLAIM_ACCOUNT turns this on per-slab
  */
 atomic_t slab_reclaim_pages;
-EXPORT_SYMBOL(slab_reclaim_pages);
 
 /*
  * chicken and egg problem: delay the per-cpu array allocation
@@ -565,7 +632,8 @@ EXPORT_SYMBOL(slab_reclaim_pages);
  */
 static enum {
        NONE,
-       PARTIAL,
+       PARTIAL_AC,
+       PARTIAL_L3,
        FULL
 } g_cpucache_up;
 
@@ -574,11 +642,7 @@ static DEFINE_PER_CPU(struct work_struct, reap_work);
 static void free_block(kmem_cache_t* cachep, void** objpp, int len);
 static void enable_cpucache (kmem_cache_t *cachep);
 static void cache_reap (void *unused);
-
-static inline void **ac_entry(struct array_cache *ac)
-{
-       return (void**)(ac+1);
-}
+static int __node_shrink(kmem_cache_t *cachep, int node);
 
 static inline struct array_cache *ac_data(kmem_cache_t *cachep)
 {
@@ -676,48 +740,160 @@ static void __devinit start_cpu_timer(int cpu)
        }
 }
 
-static struct array_cache *alloc_arraycache(int cpu, int entries,
+static struct array_cache *alloc_arraycache(int node, int entries,
                                                int batchcount)
 {
        int memsize = sizeof(void*)*entries+sizeof(struct array_cache);
        struct array_cache *nc = NULL;
 
-       if (cpu == -1)
-               nc = kmalloc(memsize, GFP_KERNEL);
-       else
-               nc = kmalloc_node(memsize, GFP_KERNEL, cpu_to_node(cpu));
-
+       nc = kmalloc_node(memsize, GFP_KERNEL, node);
        if (nc) {
                nc->avail = 0;
                nc->limit = entries;
                nc->batchcount = batchcount;
                nc->touched = 0;
+               spin_lock_init(&nc->lock);
        }
        return nc;
 }
 
+#ifdef CONFIG_NUMA
+static inline struct array_cache **alloc_alien_cache(int node, int limit)
+{
+       struct array_cache **ac_ptr;
+       int memsize = sizeof(void*)*MAX_NUMNODES;
+       int i;
+
+       if (limit > 1)
+               limit = 12;
+       ac_ptr = kmalloc_node(memsize, GFP_KERNEL, node);
+       if (ac_ptr) {
+               for_each_node(i) {
+                       if (i == node || !node_online(i)) {
+                               ac_ptr[i] = NULL;
+                               continue;
+                       }
+                       ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d);
+                       if (!ac_ptr[i]) {
+                               for (i--; i <=0; i--)
+                                       kfree(ac_ptr[i]);
+                               kfree(ac_ptr);
+                               return NULL;
+                       }
+               }
+       }
+       return ac_ptr;
+}
+
+static inline void free_alien_cache(struct array_cache **ac_ptr)
+{
+       int i;
+
+       if (!ac_ptr)
+               return;
+
+       for_each_node(i)
+               kfree(ac_ptr[i]);
+
+       kfree(ac_ptr);
+}
+
+static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache *ac, int node)
+{
+       struct kmem_list3 *rl3 = cachep->nodelists[node];
+
+       if (ac->avail) {
+               spin_lock(&rl3->list_lock);
+               free_block(cachep, ac->entry, ac->avail);
+               ac->avail = 0;
+               spin_unlock(&rl3->list_lock);
+       }
+}
+
+static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3)
+{
+       int i=0;
+       struct array_cache *ac;
+       unsigned long flags;
+
+       for_each_online_node(i) {
+               ac = l3->alien[i];
+               if (ac) {
+                       spin_lock_irqsave(&ac->lock, flags);
+                       __drain_alien_cache(cachep, ac, i);
+                       spin_unlock_irqrestore(&ac->lock, flags);
+               }
+       }
+}
+#else
+#define alloc_alien_cache(node, limit) do { } while (0)
+#define free_alien_cache(ac_ptr) do { } while (0)
+#define drain_alien_cache(cachep, l3) do { } while (0)
+#endif
+
 static int __devinit cpuup_callback(struct notifier_block *nfb,
                                  unsigned long action, void *hcpu)
 {
        long cpu = (long)hcpu;
        kmem_cache_t* cachep;
+       struct kmem_list3 *l3 = NULL;
+       int node = cpu_to_node(cpu);
+       int memsize = sizeof(struct kmem_list3);
+       struct array_cache *nc = NULL;
 
        switch (action) {
        case CPU_UP_PREPARE:
                down(&cache_chain_sem);
+               /* we need to do this right in the beginning since
+                * alloc_arraycache's are going to use this list.
+                * kmalloc_node allows us to add the slab to the right
+                * kmem_list3 and not this cpu's kmem_list3
+                */
+
                list_for_each_entry(cachep, &cache_chain, next) {
-                       struct array_cache *nc;
+                       /* setup the size64 kmemlist for cpu before we can
+                        * begin anything. Make sure some other cpu on this
+                        * node has not already allocated this
+                        */
+                       if (!cachep->nodelists[node]) {
+                               if (!(l3 = kmalloc_node(memsize,
+                                               GFP_KERNEL, node)))
+                                       goto bad;
+                               kmem_list3_init(l3);
+                               l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+                                 ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+
+                               cachep->nodelists[node] = l3;
+                       }
+
+                       spin_lock_irq(&cachep->nodelists[node]->list_lock);
+                       cachep->nodelists[node]->free_limit =
+                               (1 + nr_cpus_node(node)) *
+                               cachep->batchcount + cachep->num;
+                       spin_unlock_irq(&cachep->nodelists[node]->list_lock);
+               }
 
-                       nc = alloc_arraycache(cpu, cachep->limit, cachep->batchcount);
+               /* Now we can go ahead with allocating the shared array's
+                 & array cache's */
+               list_for_each_entry(cachep, &cache_chain, next) {
+                       nc = alloc_arraycache(node, cachep->limit,
+                                       cachep->batchcount);
                        if (!nc)
                                goto bad;
-
-                       spin_lock_irq(&cachep->spinlock);
                        cachep->array[cpu] = nc;
-                       cachep->free_limit = (1+num_online_cpus())*cachep->batchcount
-                                               + cachep->num;
-                       spin_unlock_irq(&cachep->spinlock);
 
+                       l3 = cachep->nodelists[node];
+                       BUG_ON(!l3);
+                       if (!l3->shared) {
+                               if (!(nc = alloc_arraycache(node,
+                                       cachep->shared*cachep->batchcount,
+                                       0xbaadf00d)))
+                                       goto  bad;
+
+                               /* we are serialised from CPU_DEAD or
+                                 CPU_UP_CANCELLED by the cpucontrol lock */
+                               l3->shared = nc;
+                       }
                }
                up(&cache_chain_sem);
                break;
@@ -732,13 +908,51 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
 
                list_for_each_entry(cachep, &cache_chain, next) {
                        struct array_cache *nc;
+                       cpumask_t mask;
 
+                       mask = node_to_cpumask(node);
                        spin_lock_irq(&cachep->spinlock);
                        /* cpu is dead; no one can alloc from it. */
                        nc = cachep->array[cpu];
                        cachep->array[cpu] = NULL;
-                       cachep->free_limit -= cachep->batchcount;
-                       free_block(cachep, ac_entry(nc), nc->avail);
+                       l3 = cachep->nodelists[node];
+
+                       if (!l3)
+                               goto unlock_cache;
+
+                       spin_lock(&l3->list_lock);
+
+                       /* Free limit for this kmem_list3 */
+                       l3->free_limit -= cachep->batchcount;
+                       if (nc)
+                               free_block(cachep, nc->entry, nc->avail);
+
+                       if (!cpus_empty(mask)) {
+                                spin_unlock(&l3->list_lock);
+                                goto unlock_cache;
+                        }
+
+                       if (l3->shared) {
+                               free_block(cachep, l3->shared->entry,
+                                               l3->shared->avail);
+                               kfree(l3->shared);
+                               l3->shared = NULL;
+                       }
+                       if (l3->alien) {
+                               drain_alien_cache(cachep, l3);
+                               free_alien_cache(l3->alien);
+                               l3->alien = NULL;
+                       }
+
+                       /* free slabs belonging to this node */
+                       if (__node_shrink(cachep, node)) {
+                               cachep->nodelists[node] = NULL;
+                               spin_unlock(&l3->list_lock);
+                               kfree(l3);
+                       } else {
+                               spin_unlock(&l3->list_lock);
+                       }
+unlock_cache:
                        spin_unlock_irq(&cachep->spinlock);
                        kfree(nc);
                }
@@ -754,6 +968,25 @@ bad:
 
 static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 };
 
+/*
+ * swap the static kmem_list3 with kmalloced memory
+ */
+static void init_list(kmem_cache_t *cachep, struct kmem_list3 *list,
+               int nodeid)
+{
+       struct kmem_list3 *ptr;
+
+       BUG_ON(cachep->nodelists[nodeid] != list);
+       ptr = kmalloc_node(sizeof(struct kmem_list3), GFP_KERNEL, nodeid);
+       BUG_ON(!ptr);
+
+       local_irq_disable();
+       memcpy(ptr, list, sizeof(struct kmem_list3));
+       MAKE_ALL_LISTS(cachep, ptr, nodeid);
+       cachep->nodelists[nodeid] = ptr;
+       local_irq_enable();
+}
+
 /* Initialisation.
  * Called after the gfp() functions have been enabled, and before smp_init().
  */
@@ -762,6 +995,13 @@ void __init kmem_cache_init(void)
        size_t left_over;
        struct cache_sizes *sizes;
        struct cache_names *names;
+       int i;
+
+       for (i = 0; i < NUM_INIT_LISTS; i++) {
+               kmem_list3_init(&initkmem_list3[i]);
+               if (i < MAX_NUMNODES)
+                       cache_cache.nodelists[i] = NULL;
+       }
 
        /*
         * Fragmentation resistance on low memory - only use bigger
@@ -770,21 +1010,24 @@ void __init kmem_cache_init(void)
        if (num_physpages > (32 << 20) >> PAGE_SHIFT)
                slab_break_gfp_order = BREAK_GFP_ORDER_HI;
 
-       
        /* Bootstrap is tricky, because several objects are allocated
         * from caches that do not exist yet:
         * 1) initialize the cache_cache cache: it contains the kmem_cache_t
         *    structures of all caches, except cache_cache itself: cache_cache
         *    is statically allocated.
-        *    Initially an __init data area is used for the head array, it's
-        *    replaced with a kmalloc allocated array at the end of the bootstrap.
+        *    Initially an __init data area is used for the head array and the
+        *    kmem_list3 structures, it's replaced with a kmalloc allocated
+        *    array at the end of the bootstrap.
         * 2) Create the first kmalloc cache.
-        *    The kmem_cache_t for the new cache is allocated normally. An __init
-        *    data area is used for the head array.
-        * 3) Create the remaining kmalloc caches, with minimally sized head arrays.
+        *    The kmem_cache_t for the new cache is allocated normally.
+        *    An __init data area is used for the head array.
+        * 3) Create the remaining kmalloc caches, with minimally sized
+        *    head arrays.
         * 4) Replace the __init data head arrays for cache_cache and the first
         *    kmalloc cache with kmalloc allocated arrays.
-        * 5) Resize the head arrays of the kmalloc caches to their final sizes.
+        * 5) Replace the __init data for kmem_list3 for cache_cache and
+        *    the other cache's with kmalloc allocated memory.
+        * 6) Resize the head arrays of the kmalloc caches to their final sizes.
         */
 
        /* 1) create the cache_cache */
@@ -793,6 +1036,7 @@ void __init kmem_cache_init(void)
        list_add(&cache_cache.next, &cache_chain);
        cache_cache.colour_off = cache_line_size();
        cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
+       cache_cache.nodelists[numa_node_id()] = &initkmem_list3[CACHE_CACHE];
 
        cache_cache.objsize = ALIGN(cache_cache.objsize, cache_line_size());
 
@@ -810,15 +1054,33 @@ void __init kmem_cache_init(void)
        sizes = malloc_sizes;
        names = cache_names;
 
+       /* Initialize the caches that provide memory for the array cache
+        * and the kmem_list3 structures first.
+        * Without this, further allocations will bug
+        */
+
+       sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,
+                               sizes[INDEX_AC].cs_size, ARCH_KMALLOC_MINALIGN,
+                               (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
+
+       if (INDEX_AC != INDEX_L3)
+               sizes[INDEX_L3].cs_cachep =
+                       kmem_cache_create(names[INDEX_L3].name,
+                               sizes[INDEX_L3].cs_size, ARCH_KMALLOC_MINALIGN,
+                               (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
+
        while (sizes->cs_size != ULONG_MAX) {
-               /* For performance, all the general caches are L1 aligned.
+               /*
+                * For performance, all the general caches are L1 aligned.
                 * This should be particularly beneficial on SMP boxes, as it
                 * eliminates "false sharing".
                 * Note for systems short on memory removing the alignment will
-                * allow tighter packing of the smaller caches. */
-               sizes->cs_cachep = kmem_cache_create(names->name,
-                       sizes->cs_size, ARCH_KMALLOC_MINALIGN,
-                       (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
+                * allow tighter packing of the smaller caches.
+                */
+               if(!sizes->cs_cachep)
+                       sizes->cs_cachep = kmem_cache_create(names->name,
+                               sizes->cs_size, ARCH_KMALLOC_MINALIGN,
+                               (ARCH_KMALLOC_FLAGS | SLAB_PANIC), NULL, NULL);
 
                /* Inc off-slab bufctl limit until the ceiling is hit. */
                if (!(OFF_SLAB(sizes->cs_cachep))) {
@@ -837,24 +1099,47 @@ void __init kmem_cache_init(void)
        /* 4) Replace the bootstrap head arrays */
        {
                void * ptr;
-               
+
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
+
                local_irq_disable();
                BUG_ON(ac_data(&cache_cache) != &initarray_cache.cache);
-               memcpy(ptr, ac_data(&cache_cache), sizeof(struct arraycache_init));
+               memcpy(ptr, ac_data(&cache_cache),
+                               sizeof(struct arraycache_init));
                cache_cache.array[smp_processor_id()] = ptr;
                local_irq_enable();
-       
+
                ptr = kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
+
                local_irq_disable();
-               BUG_ON(ac_data(malloc_sizes[0].cs_cachep) != &initarray_generic.cache);
-               memcpy(ptr, ac_data(malloc_sizes[0].cs_cachep),
+               BUG_ON(ac_data(malloc_sizes[INDEX_AC].cs_cachep)
+                               != &initarray_generic.cache);
+               memcpy(ptr, ac_data(malloc_sizes[INDEX_AC].cs_cachep),
                                sizeof(struct arraycache_init));
-               malloc_sizes[0].cs_cachep->array[smp_processor_id()] = ptr;
+               malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
+                                               ptr;
                local_irq_enable();
        }
+       /* 5) Replace the bootstrap kmem_list3's */
+       {
+               int node;
+               /* Replace the static kmem_list3 structures for the boot cpu */
+               init_list(&cache_cache, &initkmem_list3[CACHE_CACHE],
+                               numa_node_id());
+
+               for_each_online_node(node) {
+                       init_list(malloc_sizes[INDEX_AC].cs_cachep,
+                                       &initkmem_list3[SIZE_AC+node], node);
+
+                       if (INDEX_AC != INDEX_L3) {
+                               init_list(malloc_sizes[INDEX_L3].cs_cachep,
+                                               &initkmem_list3[SIZE_L3+node],
+                                               node);
+                       }
+               }
+       }
 
-       /* 5) resize the head arrays to their final sizes */
+       /* 6) resize the head arrays to their final sizes */
        {
                kmem_cache_t *cachep;
                down(&cache_chain_sem);
@@ -870,7 +1155,6 @@ void __init kmem_cache_init(void)
         * that initializes ac_data for all new cpus
         */
        register_cpu_notifier(&cpucache_notifier);
-       
 
        /* The reap timers are started later, with a module init call:
         * That part of the kernel is not yet operational.
@@ -885,10 +1169,8 @@ static int __init cpucache_init(void)
         * Register the timers that return unneeded
         * pages to gfp.
         */
-       for (cpu = 0; cpu < NR_CPUS; cpu++) {
-               if (cpu_online(cpu))
-                       start_cpu_timer(cpu);
-       }
+       for_each_online_cpu(cpu)
+               start_cpu_timer(cpu);
 
        return 0;
 }
@@ -1167,6 +1449,20 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
        }
 }
 
+/* For setting up all the kmem_list3s for cache whose objsize is same
+   as size of kmem_list3. */
+static inline void set_up_list3s(kmem_cache_t *cachep, int index)
+{
+       int node;
+
+       for_each_online_node(node) {
+               cachep->nodelists[node] = &initkmem_list3[index+node];
+               cachep->nodelists[node]->next_reap = jiffies +
+                       REAPTIMEOUT_LIST3 +
+                       ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+       }
+}
+
 /**
  * kmem_cache_create - Create a cache.
  * @name: A string which is used in /proc/slabinfo to identify this cache.
@@ -1320,7 +1616,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
                size += BYTES_PER_WORD;
        }
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
-       if (size > 128 && cachep->reallen > cache_line_size() && size < PAGE_SIZE) {
+       if (size >= malloc_sizes[INDEX_L3+1].cs_size && cachep->reallen > cache_line_size() && size < PAGE_SIZE) {
                cachep->dbghead += PAGE_SIZE - size;
                size = PAGE_SIZE;
        }
@@ -1422,13 +1718,9 @@ next:
                cachep->gfpflags |= GFP_DMA;
        spin_lock_init(&cachep->spinlock);
        cachep->objsize = size;
-       /* NUMA */
-       INIT_LIST_HEAD(&cachep->lists.slabs_full);
-       INIT_LIST_HEAD(&cachep->lists.slabs_partial);
-       INIT_LIST_HEAD(&cachep->lists.slabs_free);
 
        if (flags & CFLGS_OFF_SLAB)
-               cachep->slabp_cache = kmem_find_general_cachep(slab_size,0);
+               cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
        cachep->ctor = ctor;
        cachep->dtor = dtor;
        cachep->name = name;
@@ -1444,11 +1736,43 @@ next:
                         * the cache that's used by kmalloc(24), otherwise
                         * the creation of further caches will BUG().
                         */
-                       cachep->array[smp_processor_id()] = &initarray_generic.cache;
-                       g_cpucache_up = PARTIAL;
+                       cachep->array[smp_processor_id()] =
+                               &initarray_generic.cache;
+
+                       /* If the cache that's used by
+                        * kmalloc(sizeof(kmem_list3)) is the first cache,
+                        * then we need to set up all its list3s, otherwise
+                        * the creation of further caches will BUG().
+                        */
+                       set_up_list3s(cachep, SIZE_AC);
+                       if (INDEX_AC == INDEX_L3)
+                               g_cpucache_up = PARTIAL_L3;
+                       else
+                               g_cpucache_up = PARTIAL_AC;
                } else {
-                       cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init),GFP_KERNEL);
+                       cachep->array[smp_processor_id()] =
+                               kmalloc(sizeof(struct arraycache_init),
+                                               GFP_KERNEL);
+
+                       if (g_cpucache_up == PARTIAL_AC) {
+                               set_up_list3s(cachep, SIZE_L3);
+                               g_cpucache_up = PARTIAL_L3;
+                       } else {
+                               int node;
+                               for_each_online_node(node) {
+
+                                       cachep->nodelists[node] =
+                                               kmalloc_node(sizeof(struct kmem_list3),
+                                                               GFP_KERNEL, node);
+                                       BUG_ON(!cachep->nodelists[node]);
+                                       kmem_list3_init(cachep->nodelists[node]);
+                               }
+                       }
                }
+               cachep->nodelists[numa_node_id()]->next_reap =
+                       jiffies + REAPTIMEOUT_LIST3 +
+                       ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+
                BUG_ON(!ac_data(cachep));
                ac_data(cachep)->avail = 0;
                ac_data(cachep)->limit = BOOT_CPUCACHE_ENTRIES;
@@ -1456,13 +1780,8 @@ next:
                ac_data(cachep)->touched = 0;
                cachep->batchcount = 1;
                cachep->limit = BOOT_CPUCACHE_ENTRIES;
-               cachep->free_limit = (1+num_online_cpus())*cachep->batchcount
-                                       + cachep->num;
        } 
 
-       cachep->lists.next_reap = jiffies + REAPTIMEOUT_LIST3 +
-                                       ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
-
        /* Need the semaphore to access the chain. */
        down(&cache_chain_sem);
        {
@@ -1519,13 +1838,23 @@ static void check_spinlock_acquired(kmem_cache_t *cachep)
 {
 #ifdef CONFIG_SMP
        check_irq_off();
-       BUG_ON(spin_trylock(&cachep->spinlock));
+       assert_spin_locked(&cachep->nodelists[numa_node_id()]->list_lock);
 #endif
 }
+
+static inline void check_spinlock_acquired_node(kmem_cache_t *cachep, int node)
+{
+#ifdef CONFIG_SMP
+       check_irq_off();
+       assert_spin_locked(&cachep->nodelists[node]->list_lock);
+#endif
+}
+
 #else
 #define check_irq_off()        do { } while(0)
 #define check_irq_on() do { } while(0)
 #define check_spinlock_acquired(x) do { } while(0)
+#define check_spinlock_acquired_node(x, y) do { } while(0)
 #endif
 
 /*
@@ -1547,7 +1876,7 @@ static void smp_call_function_all_cpus(void (*func) (void *arg), void *arg)
 }
 
 static void drain_array_locked(kmem_cache_t* cachep,
-                               struct array_cache *ac, int force);
+                               struct array_cache *ac, int force, int node);
 
 static void do_drain(void *arg)
 {
@@ -1556,59 +1885,82 @@ static void do_drain(void *arg)
 
        check_irq_off();
        ac = ac_data(cachep);
-       spin_lock(&cachep->spinlock);
-       free_block(cachep, &ac_entry(ac)[0], ac->avail);
-       spin_unlock(&cachep->spinlock);
+       spin_lock(&cachep->nodelists[numa_node_id()]->list_lock);
+       free_block(cachep, ac->entry, ac->avail);
+       spin_unlock(&cachep->nodelists[numa_node_id()]->list_lock);
        ac->avail = 0;
 }
 
 static void drain_cpu_caches(kmem_cache_t *cachep)
 {
+       struct kmem_list3 *l3;
+       int node;
+
        smp_call_function_all_cpus(do_drain, cachep);
        check_irq_on();
        spin_lock_irq(&cachep->spinlock);
-       if (cachep->lists.shared)
-               drain_array_locked(cachep, cachep->lists.shared, 1);
+       for_each_online_node(node)  {
+               l3 = cachep->nodelists[node];
+               if (l3) {
+                       spin_lock(&l3->list_lock);
+                       drain_array_locked(cachep, l3->shared, 1, node);
+                       spin_unlock(&l3->list_lock);
+                       if (l3->alien)
+                               drain_alien_cache(cachep, l3);
+               }
+       }
        spin_unlock_irq(&cachep->spinlock);
 }
 
-
-/* NUMA shrink all list3s */
-static int __cache_shrink(kmem_cache_t *cachep)
+static int __node_shrink(kmem_cache_t *cachep, int node)
 {
        struct slab *slabp;
+       struct kmem_list3 *l3 = cachep->nodelists[node];
        int ret;
 
-       drain_cpu_caches(cachep);
-
-       check_irq_on();
-       spin_lock_irq(&cachep->spinlock);
-
-       for(;;) {
+       for (;;) {
                struct list_head *p;
 
-               p = cachep->lists.slabs_free.prev;
-               if (p == &cachep->lists.slabs_free)
+               p = l3->slabs_free.prev;
+               if (p == &l3->slabs_free)
                        break;
 
-               slabp = list_entry(cachep->lists.slabs_free.prev, struct slab, list);
+               slabp = list_entry(l3->slabs_free.prev, struct slab, list);
 #if DEBUG
                if (slabp->inuse)
                        BUG();
 #endif
                list_del(&slabp->list);
 
-               cachep->lists.free_objects -= cachep->num;
-               spin_unlock_irq(&cachep->spinlock);
+               l3->free_objects -= cachep->num;
+               spin_unlock_irq(&l3->list_lock);
                slab_destroy(cachep, slabp);
-               spin_lock_irq(&cachep->spinlock);
+               spin_lock_irq(&l3->list_lock);
        }
-       ret = !list_empty(&cachep->lists.slabs_full) ||
-               !list_empty(&cachep->lists.slabs_partial);
-       spin_unlock_irq(&cachep->spinlock);
+       ret = !list_empty(&l3->slabs_full) ||
+               !list_empty(&l3->slabs_partial);
        return ret;
 }
 
+static int __cache_shrink(kmem_cache_t *cachep)
+{
+       int ret = 0, i = 0;
+       struct kmem_list3 *l3;
+
+       drain_cpu_caches(cachep);
+
+       check_irq_on();
+       for_each_online_node(i) {
+               l3 = cachep->nodelists[i];
+               if (l3) {
+                       spin_lock_irq(&l3->list_lock);
+                       ret += __node_shrink(cachep, i);
+                       spin_unlock_irq(&l3->list_lock);
+               }
+       }
+       return (ret ? 1 : 0);
+}
+
 /**
  * kmem_cache_shrink - Shrink a cache.
  * @cachep: The cache to shrink.
@@ -1645,6 +1997,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
 int kmem_cache_destroy(kmem_cache_t * cachep)
 {
        int i;
+       struct kmem_list3 *l3;
 
        if (!cachep || in_interrupt())
                BUG();
@@ -1672,15 +2025,17 @@ int kmem_cache_destroy(kmem_cache_t * cachep)
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
                synchronize_rcu();
 
-       /* no cpu_online check required here since we clear the percpu
-        * array on cpu offline and set this to NULL.
-        */
-       for (i = 0; i < NR_CPUS; i++)
+       for_each_online_cpu(i)
                kfree(cachep->array[i]);
 
        /* NUMA: free the list3 structures */
-       kfree(cachep->lists.shared);
-       cachep->lists.shared = NULL;
+       for_each_online_node(i) {
+               if ((l3 = cachep->nodelists[i])) {
+                       kfree(l3->shared);
+                       free_alien_cache(l3->alien);
+                       kfree(l3);
+               }
+       }
        kmem_cache_free(&cache_cache, cachep);
 
        unlock_cpu_hotplug();
@@ -1690,8 +2045,8 @@ int kmem_cache_destroy(kmem_cache_t * cachep)
 EXPORT_SYMBOL(kmem_cache_destroy);
 
 /* Get the memory for a slab management obj. */
-static struct slab* alloc_slabmgmt(kmem_cache_t *cachep,
-                       void *objp, int colour_off, unsigned int __nocast local_flags)
+static struct slab* alloc_slabmgmt(kmem_cache_t *cachep, void *objp,
+                       int colour_off, unsigned int __nocast local_flags)
 {
        struct slab *slabp;
        
@@ -1722,7 +2077,7 @@ static void cache_init_objs(kmem_cache_t *cachep,
        int i;
 
        for (i = 0; i < cachep->num; i++) {
-               voidobjp = slabp->s_mem+cachep->objsize*i;
+               void *objp = slabp->s_mem+cachep->objsize*i;
 #if DEBUG
                /* need to poison the objs? */
                if (cachep->flags & SLAB_POISON)
@@ -1799,6 +2154,7 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
        size_t           offset;
        unsigned int     local_flags;
        unsigned long    ctor_flags;
+       struct kmem_list3 *l3;
 
        /* Be lazy and only check for valid flags here,
         * keeping it out of the critical path in kmem_cache_alloc().
@@ -1830,6 +2186,7 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
 
        spin_unlock(&cachep->spinlock);
 
+       check_irq_off();
        if (local_flags & __GFP_WAIT)
                local_irq_enable();
 
@@ -1841,8 +2198,9 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
         */
        kmem_flagcheck(cachep, flags);
 
-
-       /* Get mem for the objs. */
+       /* Get mem for the objs.
+        * Attempt to allocate a physical page from 'nodeid',
+        */
        if (!(objp = kmem_getpages(cachep, flags, nodeid)))
                goto failed;
 
@@ -1850,6 +2208,7 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
        if (!(slabp = alloc_slabmgmt(cachep, objp, offset, local_flags)))
                goto opps1;
 
+       slabp->nodeid = nodeid;
        set_slab_attr(cachep, slabp, objp);
 
        cache_init_objs(cachep, slabp, ctor_flags);
@@ -1857,13 +2216,14 @@ static int cache_grow(kmem_cache_t *cachep, unsigned int __nocast flags, int nod
        if (local_flags & __GFP_WAIT)
                local_irq_disable();
        check_irq_off();
-       spin_lock(&cachep->spinlock);
+       l3 = cachep->nodelists[nodeid];
+       spin_lock(&l3->list_lock);
 
        /* Make slab active. */
-       list_add_tail(&slabp->list, &(list3_data(cachep)->slabs_free));
+       list_add_tail(&slabp->list, &(l3->slabs_free));
        STATS_INC_GROWN(cachep);
-       list3_data(cachep)->free_objects += cachep->num;
-       spin_unlock(&cachep->spinlock);
+       l3->free_objects += cachep->num;
+       spin_unlock(&l3->list_lock);
        return 1;
 opps1:
        kmem_freepages(cachep, objp);
@@ -1969,7 +2329,6 @@ static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
        kmem_bufctl_t i;
        int entries = 0;
        
-       check_spinlock_acquired(cachep);
        /* Check slab's freelist to see if this obj is there. */
        for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
                entries++;
@@ -2012,10 +2371,11 @@ retry:
                 */
                batchcount = BATCHREFILL_LIMIT;
        }
-       l3 = list3_data(cachep);
+       l3 = cachep->nodelists[numa_node_id()];
+
+       BUG_ON(ac->avail > 0 || !l3);
+       spin_lock(&l3->list_lock);
 
-       BUG_ON(ac->avail > 0);
-       spin_lock(&cachep->spinlock);
        if (l3->shared) {
                struct array_cache *shared_array = l3->shared;
                if (shared_array->avail) {
@@ -2023,8 +2383,9 @@ retry:
                                batchcount = shared_array->avail;
                        shared_array->avail -= batchcount;
                        ac->avail = batchcount;
-                       memcpy(ac_entry(ac), &ac_entry(shared_array)[shared_array->avail],
-                                       sizeof(void*)*batchcount);
+                       memcpy(ac->entry,
+                               &(shared_array->entry[shared_array->avail]),
+                               sizeof(void*)*batchcount);
                        shared_array->touched = 1;
                        goto alloc_done;
                }
@@ -2051,7 +2412,8 @@ retry:
                        STATS_SET_HIGH(cachep);
 
                        /* get obj pointer */
-                       ac_entry(ac)[ac->avail++] = slabp->s_mem + slabp->free*cachep->objsize;
+                       ac->entry[ac->avail++] = slabp->s_mem +
+                               slabp->free*cachep->objsize;
 
                        slabp->inuse++;
                        next = slab_bufctl(slabp)[slabp->free];
@@ -2073,12 +2435,12 @@ retry:
 must_grow:
        l3->free_objects -= ac->avail;
 alloc_done:
-       spin_unlock(&cachep->spinlock);
+       spin_unlock(&l3->list_lock);
 
        if (unlikely(!ac->avail)) {
                int x;
-               x = cache_grow(cachep, flags, -1);
-               
+               x = cache_grow(cachep, flags, numa_node_id());
+
                // cache_grow can reenable interrupts, then ac could change.
                ac = ac_data(cachep);
                if (!x && ac->avail == 0)       // no objects in sight? abort
@@ -2088,7 +2450,7 @@ alloc_done:
                        goto retry;
        }
        ac->touched = 1;
-       return ac_entry(ac)[--ac->avail];
+       return ac->entry[--ac->avail];
 }
 
 static inline void
@@ -2160,7 +2522,7 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast fl
        if (likely(ac->avail)) {
                STATS_INC_ALLOCHIT(cachep);
                ac->touched = 1;
-               objp = ac_entry(ac)[--ac->avail];
+               objp = ac->entry[--ac->avail];
        } else {
                STATS_INC_ALLOCMISS(cachep);
                objp = cache_alloc_refill(cachep, flags);
@@ -2172,33 +2534,104 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast fl
        return objp;
 }
 
-/* 
- * NUMA: different approach needed if the spinlock is moved into
- * the l3 structure
+#ifdef CONFIG_NUMA
+/*
+ * A interface to enable slab creation on nodeid
  */
+static void *__cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
+{
+       struct list_head *entry;
+       struct slab *slabp;
+       struct kmem_list3 *l3;
+       void *obj;
+       kmem_bufctl_t next;
+       int x;
+
+       l3 = cachep->nodelists[nodeid];
+       BUG_ON(!l3);
+
+retry:
+       spin_lock(&l3->list_lock);
+       entry = l3->slabs_partial.next;
+       if (entry == &l3->slabs_partial) {
+               l3->free_touched = 1;
+               entry = l3->slabs_free.next;
+               if (entry == &l3->slabs_free)
+                       goto must_grow;
+       }
+
+       slabp = list_entry(entry, struct slab, list);
+       check_spinlock_acquired_node(cachep, nodeid);
+       check_slabp(cachep, slabp);
+
+       STATS_INC_NODEALLOCS(cachep);
+       STATS_INC_ACTIVE(cachep);
+       STATS_SET_HIGH(cachep);
+
+       BUG_ON(slabp->inuse == cachep->num);
+
+       /* get obj pointer */
+       obj =  slabp->s_mem + slabp->free*cachep->objsize;
+       slabp->inuse++;
+       next = slab_bufctl(slabp)[slabp->free];
+#if DEBUG
+       slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
+#endif
+       slabp->free = next;
+       check_slabp(cachep, slabp);
+       l3->free_objects--;
+       /* move slabp to correct slabp list: */
+       list_del(&slabp->list);
 
+       if (slabp->free == BUFCTL_END) {
+               list_add(&slabp->list, &l3->slabs_full);
+       } else {
+               list_add(&slabp->list, &l3->slabs_partial);
+       }
+
+       spin_unlock(&l3->list_lock);
+       goto done;
+
+must_grow:
+       spin_unlock(&l3->list_lock);
+       x = cache_grow(cachep, flags, nodeid);
+
+       if (!x)
+               return NULL;
+
+       goto retry;
+done:
+       return obj;
+}
+#endif
+
+/*
+ * Caller needs to acquire correct kmem_list's list_lock
+ */
 static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
 {
        int i;
-
-       check_spinlock_acquired(cachep);
-
-       /* NUMA: move add into loop */
-       cachep->lists.free_objects += nr_objects;
+       struct kmem_list3 *l3;
 
        for (i = 0; i < nr_objects; i++) {
                void *objp = objpp[i];
                struct slab *slabp;
                unsigned int objnr;
+               int nodeid = 0;
 
                slabp = GET_PAGE_SLAB(virt_to_page(objp));
+               nodeid = slabp->nodeid;
+               l3 = cachep->nodelists[nodeid];
                list_del(&slabp->list);
                objnr = (objp - slabp->s_mem) / cachep->objsize;
+               check_spinlock_acquired_node(cachep, nodeid);
                check_slabp(cachep, slabp);
+
+
 #if DEBUG
                if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
-                       printk(KERN_ERR "slab: double free detected in cache '%s', objp %p.\n",
-                                               cachep->name, objp);
+                       printk(KERN_ERR "slab: double free detected in cache "
+                                       "'%s', objp %p\n", cachep->name, objp);
                        BUG();
                }
 #endif
@@ -2206,24 +2639,23 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
                slabp->free = objnr;
                STATS_DEC_ACTIVE(cachep);
                slabp->inuse--;
+               l3->free_objects++;
                check_slabp(cachep, slabp);
 
                /* fixup slab chains */
                if (slabp->inuse == 0) {
-                       if (cachep->lists.free_objects > cachep->free_limit) {
-                               cachep->lists.free_objects -= cachep->num;
+                       if (l3->free_objects > l3->free_limit) {
+                               l3->free_objects -= cachep->num;
                                slab_destroy(cachep, slabp);
                        } else {
-                               list_add(&slabp->list,
-                               &list3_data_ptr(cachep, objp)->slabs_free);
+                               list_add(&slabp->list, &l3->slabs_free);
                        }
                } else {
                        /* Unconditionally move a slab to the end of the
                         * partial list on free - maximum time for the
                         * other objects to be freed, too.
                         */
-                       list_add_tail(&slabp->list,
-                               &list3_data_ptr(cachep, objp)->slabs_partial);
+                       list_add_tail(&slabp->list, &l3->slabs_partial);
                }
        }
 }
@@ -2231,36 +2663,38 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects)
 static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
 {
        int batchcount;
+       struct kmem_list3 *l3;
 
        batchcount = ac->batchcount;
 #if DEBUG
        BUG_ON(!batchcount || batchcount > ac->avail);
 #endif
        check_irq_off();
-       spin_lock(&cachep->spinlock);
-       if (cachep->lists.shared) {
-               struct array_cache *shared_array = cachep->lists.shared;
+       l3 = cachep->nodelists[numa_node_id()];
+       spin_lock(&l3->list_lock);
+       if (l3->shared) {
+               struct array_cache *shared_array = l3->shared;
                int max = shared_array->limit-shared_array->avail;
                if (max) {
                        if (batchcount > max)
                                batchcount = max;
-                       memcpy(&ac_entry(shared_array)[shared_array->avail],
-                                       &ac_entry(ac)[0],
+                       memcpy(&(shared_array->entry[shared_array->avail]),
+                                       ac->entry,
                                        sizeof(void*)*batchcount);
                        shared_array->avail += batchcount;
                        goto free_done;
                }
        }
 
-       free_block(cachep, &ac_entry(ac)[0], batchcount);
+       free_block(cachep, ac->entry, batchcount);
 free_done:
 #if STATS
        {
                int i = 0;
                struct list_head *p;
 
-               p = list3_data(cachep)->slabs_free.next;
-               while (p != &(list3_data(cachep)->slabs_free)) {
+               p = l3->slabs_free.next;
+               while (p != &(l3->slabs_free)) {
                        struct slab *slabp;
 
                        slabp = list_entry(p, struct slab, list);
@@ -2272,12 +2706,13 @@ free_done:
                STATS_SET_FREEABLE(cachep, i);
        }
 #endif
-       spin_unlock(&cachep->spinlock);
+       spin_unlock(&l3->list_lock);
        ac->avail -= batchcount;
-       memmove(&ac_entry(ac)[0], &ac_entry(ac)[batchcount],
+       memmove(ac->entry, &(ac->entry[batchcount]),
                        sizeof(void*)*ac->avail);
 }
 
+
 /*
  * __cache_free
  * Release an obj back to its cache. If the obj has a constructed
@@ -2292,14 +2727,46 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
        check_irq_off();
        objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
+       /* Make sure we are not freeing a object from another
+        * node to the array cache on this cpu.
+        */
+#ifdef CONFIG_NUMA
+       {
+               struct slab *slabp;
+               slabp = GET_PAGE_SLAB(virt_to_page(objp));
+               if (unlikely(slabp->nodeid != numa_node_id())) {
+                       struct array_cache *alien = NULL;
+                       int nodeid = slabp->nodeid;
+                       struct kmem_list3 *l3 = cachep->nodelists[numa_node_id()];
+
+                       STATS_INC_NODEFREES(cachep);
+                       if (l3->alien && l3->alien[nodeid]) {
+                               alien = l3->alien[nodeid];
+                               spin_lock(&alien->lock);
+                               if (unlikely(alien->avail == alien->limit))
+                                       __drain_alien_cache(cachep,
+                                                       alien, nodeid);
+                               alien->entry[alien->avail++] = objp;
+                               spin_unlock(&alien->lock);
+                       } else {
+                               spin_lock(&(cachep->nodelists[nodeid])->
+                                               list_lock);
+                               free_block(cachep, &objp, 1);
+                               spin_unlock(&(cachep->nodelists[nodeid])->
+                                               list_lock);
+                       }
+                       return;
+               }
+       }
+#endif
        if (likely(ac->avail < ac->limit)) {
                STATS_INC_FREEHIT(cachep);
-               ac_entry(ac)[ac->avail++] = objp;
+               ac->entry[ac->avail++] = objp;
                return;
        } else {
                STATS_INC_FREEMISS(cachep);
                cache_flusharray(cachep, ac);
-               ac_entry(ac)[ac->avail++] = objp;
+               ac->entry[ac->avail++] = objp;
        }
 }
 
@@ -2369,81 +2836,30 @@ out:
  * Identical to kmem_cache_alloc, except that this function is slow
  * and can sleep. And it will allocate memory on the given node, which
  * can improve the performance for cpu bound structures.
+ * New and improved: it will now make sure that the object gets
+ * put on the correct node list so that there is no false sharing.
  */
-void *kmem_cache_alloc_node(kmem_cache_t *cachep, int flags, int nodeid)
+void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, int nodeid)
 {
-       int loop;
-       void *objp;
-       struct slab *slabp;
-       kmem_bufctl_t next;
-
-       if (nodeid == -1)
-               return kmem_cache_alloc(cachep, flags);
-
-       for (loop = 0;;loop++) {
-               struct list_head *q;
-
-               objp = NULL;
-               check_irq_on();
-               spin_lock_irq(&cachep->spinlock);
-               /* walk through all partial and empty slab and find one
-                * from the right node */
-               list_for_each(q,&cachep->lists.slabs_partial) {
-                       slabp = list_entry(q, struct slab, list);
-
-                       if (page_to_nid(virt_to_page(slabp->s_mem)) == nodeid ||
-                                       loop > 2)
-                               goto got_slabp;
-               }
-               list_for_each(q, &cachep->lists.slabs_free) {
-                       slabp = list_entry(q, struct slab, list);
+       unsigned long save_flags;
+       void *ptr;
 
-                       if (page_to_nid(virt_to_page(slabp->s_mem)) == nodeid ||
-                                       loop > 2)
-                               goto got_slabp;
-               }
-               spin_unlock_irq(&cachep->spinlock);
+       if (nodeid == numa_node_id() || nodeid == -1)
+               return __cache_alloc(cachep, flags);
 
-               local_irq_disable();
-               if (!cache_grow(cachep, flags, nodeid)) {
-                       local_irq_enable();
-                       return NULL;
-               }
-               local_irq_enable();
+       if (unlikely(!cachep->nodelists[nodeid])) {
+               /* Fall back to __cache_alloc if we run into trouble */
+               printk(KERN_WARNING "slab: not allocating in inactive node %d for cache %s\n", nodeid, cachep->name);
+               return __cache_alloc(cachep,flags);
        }
-got_slabp:
-       /* found one: allocate object */
-       check_slabp(cachep, slabp);
-       check_spinlock_acquired(cachep);
-
-       STATS_INC_ALLOCED(cachep);
-       STATS_INC_ACTIVE(cachep);
-       STATS_SET_HIGH(cachep);
-       STATS_INC_NODEALLOCS(cachep);
 
-       objp = slabp->s_mem + slabp->free*cachep->objsize;
-
-       slabp->inuse++;
-       next = slab_bufctl(slabp)[slabp->free];
-#if DEBUG
-       slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
-#endif
-       slabp->free = next;
-       check_slabp(cachep, slabp);
-
-       /* move slabp to correct slabp list: */
-       list_del(&slabp->list);
-       if (slabp->free == BUFCTL_END)
-               list_add(&slabp->list, &cachep->lists.slabs_full);
-       else
-               list_add(&slabp->list, &cachep->lists.slabs_partial);
-
-       list3_data(cachep)->free_objects--;
-       spin_unlock_irq(&cachep->spinlock);
+       cache_alloc_debugcheck_before(cachep, flags);
+       local_irq_save(save_flags);
+       ptr = __cache_alloc_node(cachep, flags, nodeid);
+       local_irq_restore(save_flags);
+       ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0));
 
-       objp = cache_alloc_debugcheck_after(cachep, GFP_KERNEL, objp,
-                                       __builtin_return_address(0));
-       return objp;
+       return ptr;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_node);
 
@@ -2513,11 +2929,18 @@ void *__alloc_percpu(size_t size, size_t align)
        if (!pdata)
                return NULL;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
-               pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL,
-                                               cpu_to_node(i));
+       /*
+        * Cannot use for_each_online_cpu since a cpu may come online
+        * and we have no way of figuring out how to fix the array
+        * that we have allocated then....
+        */
+       for_each_cpu(i) {
+               int node = cpu_to_node(i);
+
+               if (node_online(node))
+                       pdata->ptrs[i] = kmalloc_node(size, GFP_KERNEL, node);
+               else
+                       pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
 
                if (!pdata->ptrs[i])
                        goto unwind_oom;
@@ -2575,6 +2998,8 @@ EXPORT_SYMBOL(kzalloc);
  * kfree - free previously allocated memory
  * @objp: pointer returned by kmalloc.
  *
+ * If @objp is NULL, no operation is performed.
+ *
  * Don't free memory not originally allocated by kmalloc()
  * or you will run into trouble.
  */
@@ -2607,11 +3032,11 @@ free_percpu(const void *objp)
        int i;
        struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
+       /*
+        * We allocate for all cpus so we cannot use for online cpu here.
+        */
+       for_each_cpu(i)
                kfree(p->ptrs[i]);
-       }
        kfree(p);
 }
 EXPORT_SYMBOL(free_percpu);
@@ -2629,6 +3054,64 @@ const char *kmem_cache_name(kmem_cache_t *cachep)
 }
 EXPORT_SYMBOL_GPL(kmem_cache_name);
 
+/*
+ * This initializes kmem_list3 for all nodes.
+ */
+static int alloc_kmemlist(kmem_cache_t *cachep)
+{
+       int node;
+       struct kmem_list3 *l3;
+       int err = 0;
+
+       for_each_online_node(node) {
+               struct array_cache *nc = NULL, *new;
+               struct array_cache **new_alien = NULL;
+#ifdef CONFIG_NUMA
+               if (!(new_alien = alloc_alien_cache(node, cachep->limit)))
+                       goto fail;
+#endif
+               if (!(new = alloc_arraycache(node, (cachep->shared*
+                               cachep->batchcount), 0xbaadf00d)))
+                       goto fail;
+               if ((l3 = cachep->nodelists[node])) {
+
+                       spin_lock_irq(&l3->list_lock);
+
+                       if ((nc = cachep->nodelists[node]->shared))
+                               free_block(cachep, nc->entry,
+                                                       nc->avail);
+
+                       l3->shared = new;
+                       if (!cachep->nodelists[node]->alien) {
+                               l3->alien = new_alien;
+                               new_alien = NULL;
+                       }
+                       l3->free_limit = (1 + nr_cpus_node(node))*
+                               cachep->batchcount + cachep->num;
+                       spin_unlock_irq(&l3->list_lock);
+                       kfree(nc);
+                       free_alien_cache(new_alien);
+                       continue;
+               }
+               if (!(l3 = kmalloc_node(sizeof(struct kmem_list3),
+                                               GFP_KERNEL, node)))
+                       goto fail;
+
+               kmem_list3_init(l3);
+               l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
+                       ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+               l3->shared = new;
+               l3->alien = new_alien;
+               l3->free_limit = (1 + nr_cpus_node(node))*
+                       cachep->batchcount + cachep->num;
+               cachep->nodelists[node] = l3;
+       }
+       return err;
+fail:
+       err = -ENOMEM;
+       return err;
+}
+
 struct ccupdate_struct {
        kmem_cache_t *cachep;
        struct array_cache *new[NR_CPUS];
@@ -2641,7 +3124,7 @@ static void do_ccupdate_local(void *info)
 
        check_irq_off();
        old = ac_data(new->cachep);
-       
+
        new->cachep->array[smp_processor_id()] = new->new[smp_processor_id()];
        new->new[smp_processor_id()] = old;
 }
@@ -2651,54 +3134,43 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
                                int shared)
 {
        struct ccupdate_struct new;
-       struct array_cache *new_shared;
-       int i;
+       int i, err;
 
        memset(&new.new,0,sizeof(new.new));
-       for (i = 0; i < NR_CPUS; i++) {
-               if (cpu_online(i)) {
-                       new.new[i] = alloc_arraycache(i, limit, batchcount);
-                       if (!new.new[i]) {
-                               for (i--; i >= 0; i--) kfree(new.new[i]);
-                               return -ENOMEM;
-                       }
-               } else {
-                       new.new[i] = NULL;
+       for_each_online_cpu(i) {
+               new.new[i] = alloc_arraycache(cpu_to_node(i), limit, batchcount);
+               if (!new.new[i]) {
+                       for (i--; i >= 0; i--) kfree(new.new[i]);
+                       return -ENOMEM;
                }
        }
        new.cachep = cachep;
 
        smp_call_function_all_cpus(do_ccupdate_local, (void *)&new);
-       
+
        check_irq_on();
        spin_lock_irq(&cachep->spinlock);
        cachep->batchcount = batchcount;
        cachep->limit = limit;
-       cachep->free_limit = (1+num_online_cpus())*cachep->batchcount + cachep->num;
+       cachep->shared = shared;
        spin_unlock_irq(&cachep->spinlock);
 
-       for (i = 0; i < NR_CPUS; i++) {
+       for_each_online_cpu(i) {
                struct array_cache *ccold = new.new[i];
                if (!ccold)
                        continue;
-               spin_lock_irq(&cachep->spinlock);
-               free_block(cachep, ac_entry(ccold), ccold->avail);
-               spin_unlock_irq(&cachep->spinlock);
+               spin_lock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
+               free_block(cachep, ccold->entry, ccold->avail);
+               spin_unlock_irq(&cachep->nodelists[cpu_to_node(i)]->list_lock);
                kfree(ccold);
        }
-       new_shared = alloc_arraycache(-1, batchcount*shared, 0xbaadf00d);
-       if (new_shared) {
-               struct array_cache *old;
 
-               spin_lock_irq(&cachep->spinlock);
-               old = cachep->lists.shared;
-               cachep->lists.shared = new_shared;
-               if (old)
-                       free_block(cachep, ac_entry(old), old->avail);
-               spin_unlock_irq(&cachep->spinlock);
-               kfree(old);
+       err = alloc_kmemlist(cachep);
+       if (err) {
+               printk(KERN_ERR "alloc_kmemlist failed for %s, error %d.\n",
+                               cachep->name, -err);
+               BUG();
        }
-
        return 0;
 }
 
@@ -2756,11 +3228,11 @@ static void enable_cpucache(kmem_cache_t *cachep)
 }
 
 static void drain_array_locked(kmem_cache_t *cachep,
-                               struct array_cache *ac, int force)
+                               struct array_cache *ac, int force, int node)
 {
        int tofree;
 
-       check_spinlock_acquired(cachep);
+       check_spinlock_acquired_node(cachep, node);
        if (ac->touched && !force) {
                ac->touched = 0;
        } else if (ac->avail) {
@@ -2768,9 +3240,9 @@ static void drain_array_locked(kmem_cache_t *cachep,
                if (tofree > ac->avail) {
                        tofree = (ac->avail+1)/2;
                }
-               free_block(cachep, ac_entry(ac), tofree);
+               free_block(cachep, ac->entry, tofree);
                ac->avail -= tofree;
-               memmove(&ac_entry(ac)[0], &ac_entry(ac)[tofree],
+               memmove(ac->entry, &(ac->entry[tofree]),
                                        sizeof(void*)*ac->avail);
        }
 }
@@ -2789,6 +3261,7 @@ static void drain_array_locked(kmem_cache_t *cachep,
 static void cache_reap(void *unused)
 {
        struct list_head *walk;
+       struct kmem_list3 *l3;
 
        if (down_trylock(&cache_chain_sem)) {
                /* Give up. Setup the next iteration. */
@@ -2809,27 +3282,32 @@ static void cache_reap(void *unused)
 
                check_irq_on();
 
-               spin_lock_irq(&searchp->spinlock);
+               l3 = searchp->nodelists[numa_node_id()];
+               if (l3->alien)
+                       drain_alien_cache(searchp, l3);
+               spin_lock_irq(&l3->list_lock);
 
-               drain_array_locked(searchp, ac_data(searchp), 0);
+               drain_array_locked(searchp, ac_data(searchp), 0,
+                               numa_node_id());
 
-               if(time_after(searchp->lists.next_reap, jiffies))
+               if (time_after(l3->next_reap, jiffies))
                        goto next_unlock;
 
-               searchp->lists.next_reap = jiffies + REAPTIMEOUT_LIST3;
+               l3->next_reap = jiffies + REAPTIMEOUT_LIST3;
 
-               if (searchp->lists.shared)
-                       drain_array_locked(searchp, searchp->lists.shared, 0);
+               if (l3->shared)
+                       drain_array_locked(searchp, l3->shared, 0,
+                               numa_node_id());
 
-               if (searchp->lists.free_touched) {
-                       searchp->lists.free_touched = 0;
+               if (l3->free_touched) {
+                       l3->free_touched = 0;
                        goto next_unlock;
                }
 
-               tofree = (searchp->free_limit+5*searchp->num-1)/(5*searchp->num);
+               tofree = (l3->free_limit+5*searchp->num-1)/(5*searchp->num);
                do {
-                       p = list3_data(searchp)->slabs_free.next;
-                       if (p == &(list3_data(searchp)->slabs_free))
+                       p = l3->slabs_free.next;
+                       if (p == &(l3->slabs_free))
                                break;
 
                        slabp = list_entry(p, struct slab, list);
@@ -2842,13 +3320,13 @@ static void cache_reap(void *unused)
                         * searchp cannot disappear, we hold
                         * cache_chain_lock
                         */
-                       searchp->lists.free_objects -= searchp->num;
-                       spin_unlock_irq(&searchp->spinlock);
+                       l3->free_objects -= searchp->num;
+                       spin_unlock_irq(&l3->list_lock);
                        slab_destroy(searchp, slabp);
-                       spin_lock_irq(&searchp->spinlock);
+                       spin_lock_irq(&l3->list_lock);
                } while(--tofree > 0);
 next_unlock:
-               spin_unlock_irq(&searchp->spinlock);
+               spin_unlock_irq(&l3->list_lock);
 next:
                cond_resched();
        }
@@ -2882,7 +3360,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
                seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
 #if STATS
                seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped>"
-                               " <error> <maxfreeable> <freelimit> <nodeallocs>");
+                               " <error> <maxfreeable> <nodeallocs> <remotefrees>");
                seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
 #endif
                seq_putc(m, '\n');
@@ -2917,39 +3395,53 @@ static int s_show(struct seq_file *m, void *p)
        unsigned long   active_objs;
        unsigned long   num_objs;
        unsigned long   active_slabs = 0;
-       unsigned long   num_slabs;
-       const char *name; 
+       unsigned long   num_slabs, free_objects = 0, shared_avail = 0;
+       const char *name;
        char *error = NULL;
+       int node;
+       struct kmem_list3 *l3;
 
        check_irq_on();
        spin_lock_irq(&cachep->spinlock);
        active_objs = 0;
        num_slabs = 0;
-       list_for_each(q,&cachep->lists.slabs_full) {
-               slabp = list_entry(q, struct slab, list);
-               if (slabp->inuse != cachep->num && !error)
-                       error = "slabs_full accounting error";
-               active_objs += cachep->num;
-               active_slabs++;
-       }
-       list_for_each(q,&cachep->lists.slabs_partial) {
-               slabp = list_entry(q, struct slab, list);
-               if (slabp->inuse == cachep->num && !error)
-                       error = "slabs_partial inuse accounting error";
-               if (!slabp->inuse && !error)
-                       error = "slabs_partial/inuse accounting error";
-               active_objs += slabp->inuse;
-               active_slabs++;
-       }
-       list_for_each(q,&cachep->lists.slabs_free) {
-               slabp = list_entry(q, struct slab, list);
-               if (slabp->inuse && !error)
-                       error = "slabs_free/inuse accounting error";
-               num_slabs++;
+       for_each_online_node(node) {
+               l3 = cachep->nodelists[node];
+               if (!l3)
+                       continue;
+
+               spin_lock(&l3->list_lock);
+
+               list_for_each(q,&l3->slabs_full) {
+                       slabp = list_entry(q, struct slab, list);
+                       if (slabp->inuse != cachep->num && !error)
+                               error = "slabs_full accounting error";
+                       active_objs += cachep->num;
+                       active_slabs++;
+               }
+               list_for_each(q,&l3->slabs_partial) {
+                       slabp = list_entry(q, struct slab, list);
+                       if (slabp->inuse == cachep->num && !error)
+                               error = "slabs_partial inuse accounting error";
+                       if (!slabp->inuse && !error)
+                               error = "slabs_partial/inuse accounting error";
+                       active_objs += slabp->inuse;
+                       active_slabs++;
+               }
+               list_for_each(q,&l3->slabs_free) {
+                       slabp = list_entry(q, struct slab, list);
+                       if (slabp->inuse && !error)
+                               error = "slabs_free/inuse accounting error";
+                       num_slabs++;
+               }
+               free_objects += l3->free_objects;
+               shared_avail += l3->shared->avail;
+
+               spin_unlock(&l3->list_lock);
        }
        num_slabs+=active_slabs;
        num_objs = num_slabs*cachep->num;
-       if (num_objs - active_objs != cachep->lists.free_objects && !error)
+       if (num_objs - active_objs != free_objects && !error)
                error = "free_objects accounting error";
 
        name = cachep->name; 
@@ -2961,9 +3453,9 @@ static int s_show(struct seq_file *m, void *p)
                cachep->num, (1<<cachep->gfporder));
        seq_printf(m, " : tunables %4u %4u %4u",
                        cachep->limit, cachep->batchcount,
-                       cachep->lists.shared->limit/cachep->batchcount);
-       seq_printf(m, " : slabdata %6lu %6lu %6u",
-                       active_slabs, num_slabs, cachep->lists.shared->avail);
+                       cachep->shared);
+       seq_printf(m, " : slabdata %6lu %6lu %6lu",
+                       active_slabs, num_slabs, shared_avail);
 #if STATS
        {       /* list3 stats */
                unsigned long high = cachep->high_mark;
@@ -2972,12 +3464,13 @@ static int s_show(struct seq_file *m, void *p)
                unsigned long reaped = cachep->reaped;
                unsigned long errors = cachep->errors;
                unsigned long max_freeable = cachep->max_freeable;
-               unsigned long free_limit = cachep->free_limit;
                unsigned long node_allocs = cachep->node_allocs;
+               unsigned long node_frees = cachep->node_frees;
 
-               seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu %4lu %4lu %4lu %4lu",
-                               allocs, high, grown, reaped, errors, 
-                               max_freeable, free_limit, node_allocs);
+               seq_printf(m, " : globalstat %7lu %6lu %5lu %4lu \
+                               %4lu %4lu %4lu %4lu",
+                               allocs, high, grown, reaped, errors,
+                               max_freeable, node_allocs, node_frees);
        }
        /* cpu stats */
        {
@@ -3056,9 +3549,10 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
                            batchcount < 1 ||
                            batchcount > limit ||
                            shared < 0) {
-                               res = -EINVAL;
+                               res = 0;
                        } else {
-                               res = do_tune_cpucache(cachep, limit, batchcount, shared);
+                               res = do_tune_cpucache(cachep, limit,
+                                                       batchcount, shared);
                        }
                        break;
                }
index 029e56eb5e77c342559954e7c18c710a5c51092e..adbc2b426c2f12aeaf1160ac0247d95bcf9a35bc 100644 (file)
@@ -67,8 +67,8 @@ void show_swap_cache_info(void)
  * __add_to_swap_cache resembles add_to_page_cache on swapper_space,
  * but sets SwapCache flag and private instead of mapping and index.
  */
-static int __add_to_swap_cache(struct page *page,
-               swp_entry_t entry, int gfp_mask)
+static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
+                              unsigned int __nocast gfp_mask)
 {
        int error;
 
index 4b6e8bf986bcad3080c23b9ad2424d24479d2f35..0184f510aacefd5cdce18b18a2d2f91008e255db 100644 (file)
@@ -1153,8 +1153,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
        p->highest_bit = 0;             /* cuts scans short */
        while (p->flags >= SWP_SCANNING) {
                spin_unlock(&swap_lock);
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1);
+               schedule_timeout_uninterruptible(1);
                spin_lock(&swap_lock);
        }
 
index 67b358e57ef67af05279196408c6c0bc430180c3..13c3d82968ae2a1e363dcc16e47474a716c5952d 100644 (file)
@@ -332,9 +332,10 @@ void __vunmap(void *addr, int deallocate_pages)
  *     @addr:          memory base address
  *
  *     Free the virtually contiguous memory area starting at @addr, as
- *     obtained from vmalloc(), vmalloc_32() or __vmalloc().
+ *     obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
+ *     NULL, no operation is performed.
  *
- *     May not be called in interrupt context.
+ *     Must not be called in interrupt context.
  */
 void vfree(void *addr)
 {
@@ -352,7 +353,7 @@ EXPORT_SYMBOL(vfree);
  *     Free the virtually contiguous memory area starting at @addr,
  *     which was created from the page array passed to vmap().
  *
- *     May not be called in interrupt context.
+ *     Must not be called in interrupt context.
  */
 void vunmap(void *addr)
 {
index 17a81ebe7e6eb0d0a1739c956d14a005c5d45186..526d9531411f5096aff51411115f62e46e1523ad 100644 (file)
@@ -105,7 +105,7 @@ extern void mpc_proc_clean(void);
 
 struct mpoa_client *mpcs = NULL; /* FIXME */
 static struct atm_mpoa_qos *qos_head = NULL;
-static struct timer_list mpc_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(mpc_timer, NULL, 0, 0);
 
 
 static struct mpoa_client *find_mpc_by_itfnum(int itf)
index 334790da9f160cd6852a35e5186db16cbb3d14b1..470c05bc4cb2bd513f1ba37002a81f46266c8905 100644 (file)
@@ -39,8 +39,7 @@ static unsigned long dst_gc_timer_inc = DST_GC_MAX;
 static void dst_run_gc(unsigned long);
 static void ___dst_free(struct dst_entry * dst);
 
-static struct timer_list dst_gc_timer =
-       TIMER_INITIALIZER(dst_run_gc, DST_GC_MIN, 0);
+static DEFINE_TIMER(dst_gc_timer, dst_run_gc, DST_GC_MIN, 0);
 
 static void dst_run_gc(unsigned long dummy)
 {
index a1a9a7abff50981c1e26fdcca3d2b7b2fa315d59..5265dfd699284a960c5fd95b33a6daf722b1a0bc 100644 (file)
@@ -645,10 +645,10 @@ int netpoll_setup(struct netpoll *np)
 
                npinfo->rx_flags = 0;
                npinfo->rx_np = NULL;
-               npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
+               spin_lock_init(&npinfo->poll_lock);
                npinfo->poll_owner = -1;
                npinfo->tries = MAX_RETRIES;
-               npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
+               spin_lock_init(&npinfo->rx_lock);
        } else
                npinfo = ndev->npinfo;
 
index 8eb083b6041a7fae844be27a29e9082e828587cc..b3ad49fa7d787ad7d8a01feb7a1a62f3faaa0bd9 100644 (file)
@@ -503,7 +503,7 @@ static int pg_delay_d = 0;
 static int pg_clone_skb_d = 0;
 static int debug = 0;
 
-static spinlock_t _thread_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(_thread_lock);
 static struct pktgen_thread *pktgen_threads = NULL;
 
 static char module_fname[128];
index 7bf3b3a91e97407a856f06acf7543df2dc39149d..e05f4f955eeee8d0bd68eae5ccfab3bc674bec8b 100644 (file)
 #include "ccid3.h"
 
 /*
- * Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
+ * Reason for maths here is to avoid 32 bit overflow when a is big.
+ * With this we get close to the limit.
  */
 static inline u32 usecs_div(const u32 a, const u32 b)
 {
-       const u32 tmp = a * (USEC_PER_SEC / 10);
-       return b > 20 ? tmp / (b / 10) : tmp;
+       const u32 div = a < (UINT_MAX / (USEC_PER_SEC /    10)) ?    10 :
+                       a < (UINT_MAX / (USEC_PER_SEC /    50)) ?    50 :
+                       a < (UINT_MAX / (USEC_PER_SEC /   100)) ?   100 :
+                       a < (UINT_MAX / (USEC_PER_SEC /   500)) ?   500 :
+                       a < (UINT_MAX / (USEC_PER_SEC /  1000)) ?  1000 :
+                       a < (UINT_MAX / (USEC_PER_SEC /  5000)) ?  5000 :
+                       a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
+                       a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
+                                                                100000;
+       const u32 tmp = a * (USEC_PER_SEC / div);
+       return (b >= 2 * div) ? tmp / (b / div) : tmp;
 }
 
 static int ccid3_debug;
@@ -68,13 +78,11 @@ static struct dccp_li_hist *ccid3_li_hist;
 
 static int ccid3_init(struct sock *sk)
 {
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
        return 0;
 }
 
 static void ccid3_exit(struct sock *sk)
 {
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 }
 
 /* TFRC sender states */
@@ -102,8 +110,7 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
 static inline void ccid3_hc_tx_set_state(struct sock *sk,
                                         enum ccid3_hc_tx_states state)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
        enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
 
        ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
@@ -144,8 +151,7 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
  */ 
 static void ccid3_hc_tx_update_x(struct sock *sk)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
        /* To avoid large error in calcX */
        if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
@@ -159,7 +165,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
        } else {
                struct timeval now;
 
-               do_gettimeofday(&now);
+               dccp_timestamp(sk, &now);
                if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
                    hctx->ccid3hctx_rtt) {
                        hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
@@ -174,9 +180,8 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
 static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
 {
        struct sock *sk = (struct sock *)data;
-       struct dccp_sock *dp = dccp_sk(sk);
        unsigned long next_tmout = 0;
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
@@ -274,20 +279,20 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
                                   struct sk_buff *skb, int len)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
        struct dccp_tx_hist_entry *new_packet;
        struct timeval now;
        long delay;
        int rc = -ENOTCONN;
 
-       /* Check if pure ACK or Terminating*/
+       BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
 
+       /* Check if pure ACK or Terminating*/
        /*
         * XXX: We only call this function for DATA and DATAACK, on, these
         * packets can have zero length, but why the comment about "pure ACK"?
         */
-       if (hctx == NULL || len == 0 ||
-           hctx->ccid3hctx_state == TFRC_SSTATE_TERM)
+       if (unlikely(len == 0))
                goto out;
 
        /* See if last packet allocated was not sent */
@@ -297,23 +302,20 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
                                                    SLAB_ATOMIC);
 
                rc = -ENOBUFS;
-               if (new_packet == NULL) {
-                       ccid3_pr_debug("%s, sk=%p, not enough mem to add "
-                                      "to history, send refused\n",
-                                      dccp_role(sk), sk);
+               if (unlikely(new_packet == NULL)) {
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough "
+                                      "mem to add to history, send refused\n",
+                                      __FUNCTION__, dccp_role(sk), sk);
                        goto out;
                }
 
                dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
        }
 
-       do_gettimeofday(&now);
+       dccp_timestamp(sk, &now);
 
        switch (hctx->ccid3hctx_state) {
        case TFRC_SSTATE_NO_SENT:
-               ccid3_pr_debug("%s, sk=%p, first packet(%llu)\n",
-                              dccp_role(sk), sk, dp->dccps_gss);
-
                hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
                hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
                sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
@@ -321,7 +323,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
                hctx->ccid3hctx_last_win_count   = 0;
                hctx->ccid3hctx_t_last_win_count = now;
                ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
-               hctx->ccid3hctx_t_ipi = TFRC_INITIAL_TIMEOUT;
+               hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI;
 
                /* Set nominal send time for initial packet */
                hctx->ccid3hctx_t_nom = now;
@@ -334,7 +336,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
        case TFRC_SSTATE_FBACK:
                delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) -
                         hctx->ccid3hctx_delta);
-               ccid3_pr_debug("send_packet delay=%ld\n", delay);
                delay /= -1000;
                /* divide by -1000 is to convert to ms and get sign right */
                rc = delay > 0 ? delay : 0;
@@ -348,29 +349,25 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
        }
 
        /* Can we send? if so add options and add to packet history */
-       if (rc == 0)
+       if (rc == 0) {
+               dp->dccps_hc_tx_insert_options = 1;
                new_packet->dccphtx_ccval =
                        DCCP_SKB_CB(skb)->dccpd_ccval =
                                hctx->ccid3hctx_last_win_count;
+       }
 out:
        return rc;
 }
 
 static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       const struct dccp_sock *dp = dccp_sk(sk);
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
        struct timeval now;
 
-       BUG_ON(hctx == NULL);
-
-       if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) {
-               ccid3_pr_debug("%s, sk=%p, while state is TFRC_SSTATE_TERM!\n",
-                              dccp_role(sk), sk);
-               return;
-       }
+       BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
 
-       do_gettimeofday(&now);
+       dccp_timestamp(sk, &now);
 
        /* check if we have sent a data packet */
        if (len > 0) {
@@ -378,14 +375,14 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
                struct dccp_tx_hist_entry *packet;
 
                packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
-               if (packet == NULL) {
-                       printk(KERN_CRIT "%s: packet doesn't exists in "
-                                        "history!\n", __FUNCTION__);
+               if (unlikely(packet == NULL)) {
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't "
+                                      "exists in history!\n", __FUNCTION__);
                        return;
                }
-               if (packet->dccphtx_sent) {
-                       printk(KERN_CRIT "%s: no unsent packet in history!\n",
-                              __FUNCTION__);
+               if (unlikely(packet->dccphtx_sent)) {
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in "
+                                      "history!\n", __FUNCTION__);
                        return;
                }
                packet->dccphtx_tstamp = now;
@@ -445,24 +442,18 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
 
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       const struct dccp_sock *dp = dccp_sk(sk);
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
        struct ccid3_options_received *opt_recv;
        struct dccp_tx_hist_entry *packet;
+       struct timeval now;
        unsigned long next_tmout; 
        u32 t_elapsed;
        u32 pinv;
        u32 x_recv;
        u32 r_sample;
 
-       if (hctx == NULL)
-               return;
-
-       if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) {
-               ccid3_pr_debug("%s, sk=%p, received a packet when "
-                              "terminating!\n", dccp_role(sk), sk);
-               return;
-       }
+       BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
 
        /* we are only interested in ACKs */
        if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
@@ -471,7 +462,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 
        opt_recv = &hctx->ccid3hctx_options_received;
 
-       t_elapsed = dp->dccps_options_received.dccpor_elapsed_time;
+       t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
        x_recv = opt_recv->ccid3or_receive_rate;
        pinv = opt_recv->ccid3or_loss_event_rate;
 
@@ -486,19 +477,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
                /* get t_recvdata from history */
                packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
                                                 DCCP_SKB_CB(skb)->dccpd_ack_seq);
-               if (packet == NULL) {
-                       ccid3_pr_debug("%s, sk=%p, seqno %llu(%s) does't "
-                                      "exist in history!\n",
-                                      dccp_role(sk), sk,
-                                      DCCP_SKB_CB(skb)->dccpd_ack_seq,
-                                      dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+               if (unlikely(packet == NULL)) {
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno "
+                                      "%llu(%s) does't exist in history!\n",
+                                      __FUNCTION__, dccp_role(sk), sk,
+                           (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
+                               dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
                        return;
                }
 
                /* Update RTT */
-               r_sample = timeval_now_delta(&packet->dccphtx_tstamp);
-               /* FIXME: */
-               // r_sample -= usecs_to_jiffies(t_elapsed * 10);
+               dccp_timestamp(sk, &now);
+               r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
+               if (unlikely(r_sample <= t_elapsed))
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
+                                      "t_elapsed=%uus\n",
+                                      __FUNCTION__, r_sample, t_elapsed);
+               else
+                       r_sample -= t_elapsed;
 
                /* Update RTT estimate by 
                 * If (No feedback recv)
@@ -591,11 +587,11 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 
 static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
 {
-       const struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+       BUG_ON(hctx == NULL);
 
-       if (hctx == NULL || !(sk->sk_state == DCCP_OPEN ||
-                             sk->sk_state == DCCP_PARTOPEN))
+       if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
                return;
 
         DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
@@ -606,12 +602,11 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
                                     unsigned char *value)
 {
        int rc = 0;
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       const struct dccp_sock *dp = dccp_sk(sk);
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
        struct ccid3_options_received *opt_recv;
 
-       if (hctx == NULL)
-               return 0;
+       BUG_ON(hctx == NULL);
 
        opt_recv = &hctx->ccid3hctx_options_received;
 
@@ -625,10 +620,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
 
        switch (option) {
        case TFRC_OPT_LOSS_EVENT_RATE:
-               if (len != 4) {
-                       ccid3_pr_debug("%s, sk=%p, invalid len for "
-                                      "TFRC_OPT_LOSS_EVENT_RATE\n",
-                                      dccp_role(sk), sk);
+               if (unlikely(len != 4)) {
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
+                                      "len for TFRC_OPT_LOSS_EVENT_RATE\n",
+                                      __FUNCTION__, dccp_role(sk), sk);
                        rc = -EINVAL;
                } else {
                        opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value);
@@ -646,10 +641,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
                               opt_recv->ccid3or_loss_intervals_len);
                break;
        case TFRC_OPT_RECEIVE_RATE:
-               if (len != 4) {
-                       ccid3_pr_debug("%s, sk=%p, invalid len for "
-                                      "TFRC_OPT_RECEIVE_RATE\n",
-                                      dccp_role(sk), sk);
+               if (unlikely(len != 4)) {
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
+                                      "len for TFRC_OPT_RECEIVE_RATE\n",
+                                      __FUNCTION__, dccp_role(sk), sk);
                        rc = -EINVAL;
                } else {
                        opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value);
@@ -668,13 +663,11 @@ static int ccid3_hc_tx_init(struct sock *sk)
        struct dccp_sock *dp = dccp_sk(sk);
        struct ccid3_hc_tx_sock *hctx;
 
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
-
-       hctx = dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx),
-                                                     gfp_any());
-       if (hctx == NULL)
+       dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
+       if (dp->dccps_hc_tx_ccid_private == NULL)
                return -ENOMEM;
 
+       hctx = ccid3_hc_tx_sk(sk);
        memset(hctx, 0, sizeof(*hctx));
 
        if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
@@ -696,9 +689,8 @@ static int ccid3_hc_tx_init(struct sock *sk)
 static void ccid3_hc_tx_exit(struct sock *sk)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
        BUG_ON(hctx == NULL);
 
        ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
@@ -738,8 +730,7 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
 static inline void ccid3_hc_rx_set_state(struct sock *sk,
                                         enum ccid3_hc_rx_states state)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
 
        ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
@@ -751,14 +742,14 @@ static inline void ccid3_hc_rx_set_state(struct sock *sk,
 
 static void ccid3_hc_rx_send_feedback(struct sock *sk)
 {
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
        struct dccp_rx_hist_entry *packet;
        struct timeval now;
 
        ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
-       do_gettimeofday(&now);
+       dccp_timestamp(sk, &now);
 
        switch (hcrx->ccid3hcrx_state) {
        case TFRC_RSTATE_NO_DATA:
@@ -767,11 +758,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
        case TFRC_RSTATE_DATA: {
                const u32 delta = timeval_delta(&now,
                                        &hcrx->ccid3hcrx_tstamp_last_feedback);
-
-               hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv *
-                                         USEC_PER_SEC);
-               if (likely(delta > 1))
-                       hcrx->ccid3hcrx_x_recv /= delta;
+               hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
+                                                  delta);
        }
                break;
        default:
@@ -782,10 +770,10 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
        }
 
        packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
-       if (packet == NULL) {
-               printk(KERN_CRIT "%s: %s, sk=%p, no data packet in history!\n",
-                      __FUNCTION__, dccp_role(sk), sk);
-               dump_stack();
+       if (unlikely(packet == NULL)) {
+               LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet "
+                              "in history!\n",
+                              __FUNCTION__, dccp_role(sk), sk);
                return;
        }
 
@@ -801,17 +789,18 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
                hcrx->ccid3hcrx_pinv = ~0;
        else
                hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
+       dp->dccps_hc_rx_insert_options = 1;
        dccp_send_ack(sk);
 }
 
 static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
 {
-       const struct dccp_sock *dp = dccp_sk(sk);
+       const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        u32 x_recv, pinv;
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
 
-       if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN ||
-                             sk->sk_state == DCCP_PARTOPEN))
+       BUG_ON(hcrx == NULL);
+
+       if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
                return;
 
        DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
@@ -837,8 +826,7 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
 
 static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
        u32 rtt, delta, x_recv, fval, p, tmp2;
        struct timeval tstamp = { 0, };
@@ -869,17 +857,17 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
                }
        }
 
-       if (step == 0) {
-               printk(KERN_CRIT "%s: %s, sk=%p, packet history contains no "
-                                "data packets!\n",
-                      __FUNCTION__, dccp_role(sk), sk);
+       if (unlikely(step == 0)) {
+               LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history "
+                              "contains no data packets!\n",
+                              __FUNCTION__, dccp_role(sk), sk);
                return ~0;
        }
 
-       if (interval == 0) {
-               ccid3_pr_debug("%s, sk=%p, Could not find a win_count "
-                              "interval > 0. Defaulting to 1\n",
-                              dccp_role(sk), sk);
+       if (unlikely(interval == 0)) {
+               LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a "
+                              "win_count interval > 0. Defaulting to 1\n",
+                              __FUNCTION__, dccp_role(sk), sk);
                interval = 1;
        }
 found:
@@ -889,10 +877,9 @@ found:
        if (rtt == 0)
                rtt = 1;
 
-       delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback);
-       x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC;
-       if (likely(delta > 1))
-               x_recv /= delta;
+       dccp_timestamp(sk, &tstamp);
+       delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
+       x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
 
        tmp1 = (u64)x_recv * (u64)rtt;
        do_div(tmp1,10000000);
@@ -911,8 +898,7 @@ found:
 
 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 
        if (seq_loss != DCCP_MAX_SEQNO + 1 &&
            list_empty(&hcrx->ccid3hcrx_li_hist)) {
@@ -924,14 +910,14 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
                if (li_tail == NULL)
                        return;
                li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
-       }
-       /* FIXME: find end of interval */
+       } else
+                   LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of "
+                                  "interval\n", __FUNCTION__);
 }
 
 static void ccid3_hc_rx_detect_loss(struct sock *sk)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        u8 win_loss;
        const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,
                                                      &hcrx->ccid3hcrx_li_hist,
@@ -942,22 +928,19 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
 
 static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
-       struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        const struct dccp_options_received *opt_recv;
        struct dccp_rx_hist_entry *packet;
        struct timeval now;
        u8 win_count;
-       u32 p_prev;
+       u32 p_prev, r_sample, t_elapsed;
        int ins;
 
-       if (hcrx == NULL)
-               return;
-
-       BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
+       BUG_ON(hcrx == NULL ||
+              !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
                 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
 
-       opt_recv = &dp->dccps_options_received;
+       opt_recv = &dccp_sk(sk)->dccps_options_received;
 
        switch (DCCP_SKB_CB(skb)->dccpd_type) {
        case DCCP_PKT_ACK:
@@ -967,10 +950,24 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                if (opt_recv->dccpor_timestamp_echo == 0)
                        break;
                p_prev = hcrx->ccid3hcrx_rtt;
-               do_gettimeofday(&now);
-               hcrx->ccid3hcrx_rtt = timeval_usecs(&now) -
-                                    (opt_recv->dccpor_timestamp_echo -
-                                     opt_recv->dccpor_elapsed_time) * 10;
+               dccp_timestamp(sk, &now);
+               timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
+               r_sample = timeval_usecs(&now);
+               t_elapsed = opt_recv->dccpor_elapsed_time * 10;
+
+               if (unlikely(r_sample <= t_elapsed))
+                       LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
+                                      "t_elapsed=%uus\n",
+                                      __FUNCTION__, r_sample, t_elapsed);
+               else
+                       r_sample -= t_elapsed;
+
+               if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
+                       hcrx->ccid3hcrx_rtt = r_sample;
+               else
+                       hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
+                                             r_sample / 10;
+
                if (p_prev != hcrx->ccid3hcrx_rtt)
                        ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
                                       dccp_role(sk), hcrx->ccid3hcrx_rtt,
@@ -978,19 +975,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                break;
        case DCCP_PKT_DATA:
                break;
-       default:
-               ccid3_pr_debug("%s, sk=%p, not DATA/DATAACK/ACK packet(%s)\n",
-                              dccp_role(sk), sk,
-                              dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
+       default: /* We're not interested in other packet types, move along */
                return;
        }
 
-       packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
+       packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
                                        skb, SLAB_ATOMIC);
-       if (packet == NULL) {
-               ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet "
-                              "to history (consider it lost)!",
-                              dccp_role(sk), sk);
+       if (unlikely(packet == NULL)) {
+               LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to "
+                               "add rx packet to history, consider it lost!\n",
+                              __FUNCTION__, dccp_role(sk), sk);
                return;
        }
 
@@ -1017,7 +1011,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
                if (ins != 0)
                        break;
 
-               do_gettimeofday(&now);
+               dccp_timestamp(sk, &now);
                if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
                    hcrx->ccid3hcrx_rtt) {
                        hcrx->ccid3hcrx_tstamp_last_ack = now;
@@ -1056,11 +1050,11 @@ static int ccid3_hc_rx_init(struct sock *sk)
 
        ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
-       hcrx = dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx),
-                                                     gfp_any());
-       if (hcrx == NULL)
+       dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
+       if (dp->dccps_hc_rx_ccid_private == NULL)
                return -ENOMEM;
 
+       hcrx = ccid3_hc_rx_sk(sk);
        memset(hcrx, 0, sizeof(*hcrx));
 
        if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
@@ -1072,23 +1066,18 @@ static int ccid3_hc_rx_init(struct sock *sk)
        hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
        INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
        INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
-       /*
-        * XXX this seems to be paranoid, need to think more about this, for
-        * now start with something different than zero. -acme
-        */
-       hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5;
+       dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
+       hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
+       hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
        return 0;
 }
 
 static void ccid3_hc_rx_exit(struct sock *sk)
 {
+       struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
        struct dccp_sock *dp = dccp_sk(sk);
-       struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
 
-       ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
-
-       if (hcrx == NULL)
-               return;
+       BUG_ON(hcrx == NULL);
 
        ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
 
@@ -1104,11 +1093,9 @@ static void ccid3_hc_rx_exit(struct sock *sk)
 
 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 {
-       const struct dccp_sock *dp = dccp_sk(sk);
-       const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+       const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 
-       if (hcrx == NULL)
-               return;
+       BUG_ON(hcrx == NULL);
 
        info->tcpi_ca_state     = hcrx->ccid3hcrx_state;
        info->tcpi_options      |= TCPI_OPT_TIMESTAMPS;
@@ -1117,11 +1104,9 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 
 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
 {
-       const struct dccp_sock *dp = dccp_sk(sk);
-       const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+       const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
-       if (hctx == NULL)
-               return;
+       BUG_ON(hctx == NULL);
 
        info->tcpi_rto = hctx->ccid3hctx_t_rto;
        info->tcpi_rtt = hctx->ccid3hctx_rtt;
index ee8cbace6630a6ca443679d428000b0b2a602d25..eb248778eea371fc34d3f053b366c9de98496b8b 100644 (file)
@@ -48,6 +48,8 @@
 /* Two seconds as per CCID3 spec */
 #define TFRC_INITIAL_TIMEOUT      (2 * USEC_PER_SEC)
 
+#define TFRC_INITIAL_IPI          (USEC_PER_SEC / 4)
+
 /* In usecs - half the scheduling granularity as per RFC3448 4.6 */
 #define TFRC_OPSYS_HALF_TIME_GRAN  (USEC_PER_SEC / (2 * HZ))
 
@@ -115,7 +117,7 @@ struct ccid3_hc_rx_sock {
        u64                     ccid3hcrx_seqno_last_counter:48,
                                ccid3hcrx_state:8,
                                ccid3hcrx_last_counter:4;
-       unsigned long           ccid3hcrx_rtt;
+       u32                     ccid3hcrx_rtt;
        u32                     ccid3hcrx_p;
        u32                     ccid3hcrx_bytes_recv;
        struct timeval          ccid3hcrx_tstamp_last_feedback;
@@ -128,10 +130,14 @@ struct ccid3_hc_rx_sock {
        u32                     ccid3hcrx_x_recv;
 };
 
-#define ccid3_hc_tx_field(s,field) (s->dccps_hc_tx_ccid_private == NULL ? 0 : \
-    ((struct ccid3_hc_tx_sock *)s->dccps_hc_tx_ccid_private)->ccid3hctx_##field)
+static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
+{
+    return dccp_sk(sk)->dccps_hc_tx_ccid_private;
+}
 
-#define ccid3_hc_rx_field(s,field) (s->dccps_hc_rx_ccid_private == NULL ? 0 : \
-    ((struct ccid3_hc_rx_sock *)s->dccps_hc_rx_ccid_private)->ccid3hcrx_##field)
+static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
+{
+    return dccp_sk(sk)->dccps_hc_rx_ccid_private;
+}
 
 #endif /* _DCCP_CCID3_H_ */
index fb90a91aa93d64816789dc2c250fdebcd6923784..b375ebdb7dcfb0766f6700ebfc3829ce4aa508b5 100644 (file)
@@ -134,6 +134,7 @@ static inline struct dccp_tx_hist_entry *
 
 static inline struct dccp_rx_hist_entry *
                     dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
+                                           const struct sock *sk, 
                                            const u32 ndp, 
                                            const struct sk_buff *skb,
                                            const unsigned int __nocast prio)
@@ -148,7 +149,7 @@ static inline struct dccp_rx_hist_entry *
                entry->dccphrx_ccval = dh->dccph_ccval;
                entry->dccphrx_type  = dh->dccph_type;
                entry->dccphrx_ndp   = ndp;
-               do_gettimeofday(&(entry->dccphrx_tstamp));
+               dccp_timestamp(sk, &entry->dccphrx_tstamp);
        }
 
        return entry;
index 33456c0d5937c8950b1a525b7d156e63adc52077..95c4630b3b18454260b34209da7e54ae326ab8a1 100644 (file)
@@ -426,10 +426,13 @@ extern struct dccp_ackpkts *
                dccp_ackpkts_alloc(unsigned int len,
                                  const unsigned int __nocast priority);
 extern void dccp_ackpkts_free(struct dccp_ackpkts *ap);
-extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state);
+extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
+                           u64 ackno, u8 state);
 extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
                                         struct sock *sk, u64 ackno);
 
+extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
+
 static inline suseconds_t timeval_usecs(const struct timeval *tv)
 {
        return tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
@@ -468,17 +471,6 @@ static inline void timeval_sub_usecs(struct timeval *tv,
        }
 }
 
-/*
- * Returns the difference in usecs between timeval
- * passed in and current time
- */
-static inline suseconds_t timeval_now_delta(const struct timeval *tv)
-{
-       struct timeval now;
-       do_gettimeofday(&now);
-       return timeval_delta(&now, tv);
-}
-
 #ifdef CONFIG_IP_DCCP_DEBUG
 extern void dccp_ackvector_print(const u64 ackno,
                                 const unsigned char *vector, int len);
index ef29cef1dafe238196224bd8aed79cc139a2c329..c60bc3433f5eac378d8a4b87198276576fd6d7f8 100644 (file)
@@ -170,7 +170,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
        if (dp->dccps_options.dccpo_send_ack_vector) {
                struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
 
-               if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
+               if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
                                     DCCP_SKB_CB(skb)->dccpd_seq,
                                     DCCP_ACKPKTS_STATE_RECEIVED)) {
                        LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
@@ -498,7 +498,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                 * DCCP_ACKPKTS_STATE_ECN_MARKED
                 */
                if (dp->dccps_options.dccpo_send_ack_vector) {
-                       if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
+                       if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
                                             DCCP_SKB_CB(skb)->dccpd_seq,
                                             DCCP_ACKPKTS_STATE_RECEIVED))
                                goto discard;
index 3fc75dbee4b8e4d068a0b4598fc96900c5a90842..2afaa464e7f0912fc812855831d8e7f73f601030 100644 (file)
@@ -641,16 +641,12 @@ int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
 
        skb = dccp_make_reset(sk, sk->sk_dst_cache, code);
        if (skb != NULL) {
-               const struct dccp_sock *dp = dccp_sk(sk);
                const struct inet_sock *inet = inet_sk(sk);
 
                err = ip_build_and_send_pkt(skb, sk,
                                            inet->saddr, inet->daddr, NULL);
                if (err == NET_XMIT_CN)
                        err = 0;
-
-               ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
-               ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
        }
 
        return err;
@@ -1243,6 +1239,7 @@ static int dccp_v4_init_sock(struct sock *sk)
        static int dccp_ctl_socket_init = 1;
 
        dccp_options_init(&dp->dccps_options);
+       do_gettimeofday(&dp->dccps_epoch);
 
        if (dp->dccps_options.dccpo_send_ack_vector) {
                dp->dccps_hc_rx_ackpkts =
index ce5dff4ac22ea9435a15b20a9da054487879aefe..18461bc04cbefae76dc8073878a53ec51bda0885 100644 (file)
@@ -96,6 +96,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
                newdp->dccps_hc_rx_ackpkts = NULL;
                newdp->dccps_role = DCCP_ROLE_SERVER;
                newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
+               do_gettimeofday(&newdp->dccps_epoch);
 
                if (newdp->dccps_options.dccpo_send_ack_vector) {
                        newdp->dccps_hc_rx_ackpkts =
index 382c5894acb20590ba4943181130ffdae9dd0f19..d4c4242d8dd7c5de227784b42c048f5f18b41027 100644 (file)
@@ -72,6 +72,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
        struct dccp_options_received *opt_recv = &dp->dccps_options_received;
        unsigned char opt, len;
        unsigned char *value;
+       u32 elapsed_time;
 
        memset(opt_recv, 0, sizeof(*opt_recv));
 
@@ -139,7 +140,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
                        opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
 
                        dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
-                       do_gettimeofday(&dp->dccps_timestamp_time);
+                       dccp_timestamp(sk, &dp->dccps_timestamp_time);
 
                        dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
                                      debug_prefix, opt_recv->dccpor_timestamp,
@@ -159,18 +160,18 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
                                      (unsigned long long)
                                      DCCP_SKB_CB(skb)->dccpd_ack_seq);
 
-                       if (len > 4) {
-                               if (len == 6)
-                                       opt_recv->dccpor_elapsed_time =
-                                                ntohs(*(u16 *)(value + 4));
-                               else
-                                       opt_recv->dccpor_elapsed_time =
-                                                ntohl(*(u32 *)(value + 4));
 
-                               dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n",
-                                     debug_prefix,
-                                     opt_recv->dccpor_elapsed_time);
-                       }
+                       if (len == 4)
+                               break;
+
+                       if (len == 6)
+                               elapsed_time = ntohs(*(u16 *)(value + 4));
+                       else
+                               elapsed_time = ntohl(*(u32 *)(value + 4));
+
+                       /* Give precedence to the biggest ELAPSED_TIME */
+                       if (elapsed_time > opt_recv->dccpor_elapsed_time)
+                               opt_recv->dccpor_elapsed_time = elapsed_time;
                        break;
                case DCCPO_ELAPSED_TIME:
                        if (len != 2 && len != 4)
@@ -180,14 +181,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
                                continue;
 
                        if (len == 2)
-                               opt_recv->dccpor_elapsed_time =
-                                                       ntohs(*(u16 *)value);
+                               elapsed_time = ntohs(*(u16 *)value);
                        else
-                               opt_recv->dccpor_elapsed_time =
-                                                       ntohl(*(u32 *)value);
+                               elapsed_time = ntohl(*(u32 *)value);
+
+                       if (elapsed_time > opt_recv->dccpor_elapsed_time)
+                               opt_recv->dccpor_elapsed_time = elapsed_time;
 
                        dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
-                                     opt_recv->dccpor_elapsed_time);
+                                     elapsed_time);
                        break;
                        /*
                         * From draft-ietf-dccp-spec-11.txt:
@@ -359,9 +361,13 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
 #endif
        struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
        int len = ap->dccpap_buf_vector_len + 2;
-       const u32 elapsed_time = timeval_now_delta(&ap->dccpap_time) / 10;
+       struct timeval now;
+       u32 elapsed_time;
        unsigned char *to, *from;
 
+       dccp_timestamp(sk, &now);
+       elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
+
        if (elapsed_time != 0)
                dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
 
@@ -426,13 +432,29 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
                      (unsigned long long) ap->dccpap_ack_ackno);
 }
 
+void dccp_timestamp(const struct sock *sk, struct timeval *tv)
+{
+       const struct dccp_sock *dp = dccp_sk(sk);
+
+       do_gettimeofday(tv);
+       tv->tv_sec  -= dp->dccps_epoch.tv_sec;
+       tv->tv_usec -= dp->dccps_epoch.tv_usec;
+
+       while (tv->tv_usec < 0) {
+               tv->tv_sec--;
+               tv->tv_usec += USEC_PER_SEC;
+       }
+}
+
+EXPORT_SYMBOL_GPL(dccp_timestamp);
+
 void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
 {
        struct timeval tv;
        u32 now;
        
-       do_gettimeofday(&tv);
-       now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10;
+       dccp_timestamp(sk, &tv);
+       now = timeval_usecs(&tv) / 10;
        /* yes this will overflow but that is the point as we want a
         * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
 
@@ -450,13 +472,17 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
        const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
                                        "CLIENT TX opt: " : "server TX opt: ";
 #endif
+       struct timeval now;
        u32 tstamp_echo;
-       const u32 elapsed_time =
-                       timeval_now_delta(&dp->dccps_timestamp_time) / 10;
-       const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
-       const int len = 6 + elapsed_time_len;
+       u32 elapsed_time;
+       int len, elapsed_time_len;
        unsigned char *to;
 
+       dccp_timestamp(sk, &now);
+       elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10;
+       elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
+       len = 6 + elapsed_time_len;
+
        if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
                LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
                                         "timestamp echo!\n");
@@ -505,13 +531,18 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
                    (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
                     DCCP_MAX_SEQNO + 1))
                        dccp_insert_option_ack_vector(sk, skb);
-
                if (dp->dccps_timestamp_echo != 0)
                        dccp_insert_option_timestamp_echo(sk, skb);
        }
 
-       ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
-       ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
+       if (dp->dccps_hc_rx_insert_options) {
+               ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
+               dp->dccps_hc_rx_insert_options = 0;
+       }
+       if (dp->dccps_hc_tx_insert_options) {
+               ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
+               dp->dccps_hc_tx_insert_options = 0;
+       }
 
        /* XXX: insert other options when appropriate */
 
@@ -616,7 +647,8 @@ static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
 /*
  * Implements the draft-ietf-dccp-spec-11.txt Appendix A
  */
-int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
+int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
+                    u64 ackno, u8 state)
 {
        /*
         * Check at the right places if the buffer is full, if it is, tell the
@@ -697,7 +729,7 @@ int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
        }
 
        ap->dccpap_buf_ackno = ackno;
-       do_gettimeofday(&ap->dccpap_time);
+       dccp_timestamp(sk, &ap->dccpap_time);
 out:
        dccp_pr_debug("");
        dccp_ackpkts_print(ap);
index 28de157a432617323385395ccc6b05f10c873085..ea6d0e91e5117ac8f5ca1b5dbbce4a5c53269696 100644 (file)
@@ -522,7 +522,4 @@ void dccp_send_close(struct sock *sk, const int active)
                dccp_transmit_skb(sk, skb_clone(skb, prio));
        } else
                dccp_transmit_skb(sk, skb);
-
-       ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
-       ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
 }
index 2c915f305be37ffef87997ae5fbab5a166103c3b..3407f190afe8892699025bf504c73111a082b8b5 100644 (file)
@@ -117,8 +117,7 @@ static struct dn_rt_hash_bucket *dn_rt_hash_table;
 static unsigned dn_rt_hash_mask;
 
 static struct timer_list dn_route_timer;
-static struct timer_list dn_rt_flush_timer =
-               TIMER_INITIALIZER(dn_run_flush, 0, 0);
+static DEFINE_TIMER(dn_rt_flush_timer, dn_run_flush, 0, 0);
 int decnet_dst_gc_interval = 2;
 
 static struct dst_ops dn_dst_ops = {
index bf147f8db399489260d2292409ba5749b1ef93e8..a9d84f93442c9560a8e7050a60292876b09bd508 100644 (file)
@@ -1248,11 +1248,6 @@ module_init(inet_init);
 /* ------------------------------------------------------------------------ */
 
 #ifdef CONFIG_PROC_FS
-#ifdef CONFIG_IP_FIB_TRIE
-extern int  fib_stat_proc_init(void);
-extern void fib_stat_proc_exit(void);
-#endif
-
 static int __init ipv4_proc_init(void)
 {
        int rc = 0;
@@ -1265,19 +1260,11 @@ static int __init ipv4_proc_init(void)
                goto out_udp;
        if (fib_proc_init())
                goto out_fib;
-#ifdef CONFIG_IP_FIB_TRIE
-         if (fib_stat_proc_init())
-                 goto out_fib_stat;
-#endif
        if (ip_misc_proc_init())
                goto out_misc;
 out:
        return rc;
 out_misc:
-#ifdef CONFIG_IP_FIB_TRIE
-       fib_stat_proc_exit();
-out_fib_stat:
-#endif
        fib_proc_exit();
 out_fib:
        udp4_proc_exit();
index b2dea4e5da77cfe2f00bf09cfaa5a0ec0e171ed5..1b63b4824164390daa515a4baf1c1e8b6f8a9b8f 100644 (file)
@@ -43,7 +43,7 @@
  *             2 of the License, or (at your option) any later version.
  */
 
-#define VERSION "0.402"
+#define VERSION "0.403"
 
 #include <linux/config.h>
 #include <asm/uaccess.h>
@@ -164,7 +164,6 @@ static struct node *resize(struct trie *t, struct tnode *tn);
 static struct tnode *inflate(struct trie *t, struct tnode *tn);
 static struct tnode *halve(struct trie *t, struct tnode *tn);
 static void tnode_free(struct tnode *tn);
-static void trie_dump_seq(struct seq_file *seq, struct trie *t);
 
 static kmem_cache_t *fn_alias_kmem __read_mostly;
 static struct trie *trie_local = NULL, *trie_main = NULL;
@@ -1971,558 +1970,525 @@ struct fib_table * __init fib_hash_init(int id)
        return tb;
 }
 
-/* Trie dump functions */
+#ifdef CONFIG_PROC_FS
+/* Depth first Trie walk iterator */
+struct fib_trie_iter {
+       struct tnode *tnode;
+       struct trie *trie;
+       unsigned index;
+       unsigned depth;
+};
 
-static void putspace_seq(struct seq_file *seq, int n)
+static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
 {
-       while (n--)
-               seq_printf(seq, " ");
-}
+       struct tnode *tn = iter->tnode;
+       unsigned cindex = iter->index;
+       struct tnode *p;
 
-static void printbin_seq(struct seq_file *seq, unsigned int v, int bits)
-{
-       while (bits--)
-               seq_printf(seq, "%s", (v & (1<<bits))?"1":"0");
-}
+       pr_debug("get_next iter={node=%p index=%d depth=%d}\n",
+                iter->tnode, iter->index, iter->depth);
+rescan:
+       while (cindex < (1<<tn->bits)) {
+               struct node *n = tnode_get_child(tn, cindex);
 
-static void printnode_seq(struct seq_file *seq, int indent, struct node *n,
-                  int pend, int cindex, int bits)
-{
-       putspace_seq(seq, indent);
-       if (IS_LEAF(n))
-               seq_printf(seq, "|");
-       else
-               seq_printf(seq, "+");
-       if (bits) {
-               seq_printf(seq, "%d/", cindex);
-               printbin_seq(seq, cindex, bits);
-               seq_printf(seq, ": ");
-       } else
-               seq_printf(seq, "<root>: ");
-       seq_printf(seq, "%s:%p ", IS_LEAF(n)?"Leaf":"Internal node", n);
+               if (n) {
+                       if (IS_LEAF(n)) {
+                               iter->tnode = tn;
+                               iter->index = cindex + 1;
+                       } else {
+                               /* push down one level */
+                               iter->tnode = (struct tnode *) n;
+                               iter->index = 0;
+                               ++iter->depth;
+                       }
+                       return n;
+               }
 
-       if (IS_LEAF(n)) {
-               struct leaf *l = (struct leaf *)n;
-               struct fib_alias *fa;
-               int i;
+               ++cindex;
+       }
 
-               seq_printf(seq, "key=%d.%d.%d.%d\n",
-                          n->key >> 24, (n->key >> 16) % 256, (n->key >> 8) % 256, n->key % 256);
-
-               for (i = 32; i >= 0; i--)
-                       if (find_leaf_info(&l->list, i)) {
-                               struct list_head *fa_head = get_fa_head(l, i);
-
-                               if (!fa_head)
-                                       continue;
-
-                               if (list_empty(fa_head))
-                                       continue;
-
-                               putspace_seq(seq, indent+2);
-                               seq_printf(seq, "{/%d...dumping}\n", i);
-
-                               list_for_each_entry_rcu(fa, fa_head, fa_list) {
-                                       putspace_seq(seq, indent+2);
-                                       if (fa->fa_info == NULL) {
-                                               seq_printf(seq, "Error fa_info=NULL\n");
-                                               continue;
-                                       }
-                                       if (fa->fa_info->fib_nh == NULL) {
-                                               seq_printf(seq, "Error _fib_nh=NULL\n");
-                                               continue;
-                                       }
-
-                                       seq_printf(seq, "{type=%d scope=%d TOS=%d}\n",
-                                             fa->fa_type,
-                                             fa->fa_scope,
-                                             fa->fa_tos);
-                               }
-                       }
-       } else {
-               struct tnode *tn = (struct tnode *)n;
-               int plen = ((struct tnode *)n)->pos;
-               t_key prf = MASK_PFX(n->key, plen);
-
-               seq_printf(seq, "key=%d.%d.%d.%d/%d\n",
-                          prf >> 24, (prf >> 16) % 256, (prf >> 8) % 256, prf % 256, plen);
-
-               putspace_seq(seq, indent); seq_printf(seq, "|    ");
-               seq_printf(seq, "{key prefix=%08x/", tn->key & TKEY_GET_MASK(0, tn->pos));
-               printbin_seq(seq, tkey_extract_bits(tn->key, 0, tn->pos), tn->pos);
-               seq_printf(seq, "}\n");
-               putspace_seq(seq, indent); seq_printf(seq, "|    ");
-               seq_printf(seq, "{pos=%d", tn->pos);
-               seq_printf(seq, " (skip=%d bits)", tn->pos - pend);
-               seq_printf(seq, " bits=%d (%u children)}\n", tn->bits, (1 << tn->bits));
-               putspace_seq(seq, indent); seq_printf(seq, "|    ");
-               seq_printf(seq, "{empty=%d full=%d}\n", tn->empty_children, tn->full_children);
+       /* Current node exhausted, pop back up */
+       p = NODE_PARENT(tn);
+       if (p) {
+               cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
+               tn = p;
+               --iter->depth;
+               goto rescan;
        }
+
+       /* got root? */
+       return NULL;
 }
 
-static void trie_dump_seq(struct seq_file *seq, struct trie *t)
+static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
+                                      struct trie *t)
 {
-       struct node *n;
-       int cindex = 0;
-       int indent = 1;
-       int pend = 0;
-       int depth = 0;
-       struct tnode *tn;
-
-       rcu_read_lock();
-       n = rcu_dereference(t->trie);
-       seq_printf(seq, "------ trie_dump of t=%p ------\n", t);
+       struct node *n = rcu_dereference(t->trie);
 
-       if (!n) {
-               seq_printf(seq, "------ trie is empty\n");
-
-               rcu_read_unlock();
-               return;
+       if (n && IS_TNODE(n)) {
+               iter->tnode = (struct tnode *) n;
+               iter->trie = t;
+               iter->index = 0;
+               iter->depth = 0;
+               return n;
        }
+       return NULL;
+}
 
-       printnode_seq(seq, indent, n, pend, cindex, 0);
-
-       if (!IS_TNODE(n)) {
-               rcu_read_unlock();
-               return;
-       }
-
-       tn = (struct tnode *)n;
-       pend = tn->pos+tn->bits;
-       putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
-       indent += 3;
-       depth++;
-
-       while (tn && cindex < (1 << tn->bits)) {
-               struct node *child = rcu_dereference(tn->child[cindex]);
-               if (!child)
-                       cindex++;
-               else {
-                       /* Got a child */
-                       printnode_seq(seq, indent, child, pend,
-                                     cindex, tn->bits);
-
-                       if (IS_LEAF(child))
-                               cindex++;
-
-                       else {
-                               /*
-                                * New tnode. Decend one level
-                                */
-
-                               depth++;
-                               n = child;
-                               tn = (struct tnode *)n;
-                               pend = tn->pos+tn->bits;
-                               putspace_seq(seq, indent);
-                               seq_printf(seq, "\\--\n");
-                               indent += 3;
-                               cindex = 0;
-                       }
-               }
-
-               /*
-                * Test if we are done
-                */
-
-               while (cindex >= (1 << tn->bits)) {
-                       /*
-                        * Move upwards and test for root
-                        * pop off all traversed  nodes
-                        */
+static void trie_collect_stats(struct trie *t, struct trie_stat *s)
+{
+       struct node *n;
+       struct fib_trie_iter iter;
 
-                       if (NODE_PARENT(tn) == NULL) {
-                               tn = NULL;
-                               break;
-                       }
+       memset(s, 0, sizeof(*s));
 
-                       cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
-                       cindex++;
-                       tn = NODE_PARENT(tn);
-                       pend = tn->pos + tn->bits;
-                       indent -= 3;
-                       depth--;
+       rcu_read_lock();
+       for (n = fib_trie_get_first(&iter, t); n;
+            n = fib_trie_get_next(&iter)) {
+               if (IS_LEAF(n)) {
+                       s->leaves++;
+                       s->totdepth += iter.depth;
+                       if (iter.depth > s->maxdepth)
+                               s->maxdepth = iter.depth;
+               } else {
+                       const struct tnode *tn = (const struct tnode *) n;
+                       int i;
+
+                       s->tnodes++;
+                       s->nodesizes[tn->bits]++;
+                       for (i = 0; i < (1<<tn->bits); i++)
+                               if (!tn->child[i])
+                                       s->nullpointers++;
                }
        }
        rcu_read_unlock();
 }
 
-static struct trie_stat *trie_stat_new(void)
+/*
+ *     This outputs /proc/net/fib_triestats
+ */
+static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
 {
-       struct trie_stat *s;
-       int i;
+       unsigned i, max, pointers, bytes, avdepth;
 
-       s = kmalloc(sizeof(struct trie_stat), GFP_KERNEL);
-       if (!s)
-               return NULL;
+       if (stat->leaves)
+               avdepth = stat->totdepth*100 / stat->leaves;
+       else
+               avdepth = 0;
 
-       s->totdepth = 0;
-       s->maxdepth = 0;
-       s->tnodes = 0;
-       s->leaves = 0;
-       s->nullpointers = 0;
+       seq_printf(seq, "\tAver depth:     %d.%02d\n", avdepth / 100, avdepth % 100 );
+       seq_printf(seq, "\tMax depth:      %u\n", stat->maxdepth);
 
-       for (i = 0; i < MAX_CHILDS; i++)
-               s->nodesizes[i] = 0;
+       seq_printf(seq, "\tLeaves:         %u\n", stat->leaves);
 
-       return s;
-}
+       bytes = sizeof(struct leaf) * stat->leaves;
+       seq_printf(seq, "\tInternal nodes: %d\n\t", stat->tnodes);
+       bytes += sizeof(struct tnode) * stat->tnodes;
 
-static struct trie_stat *trie_collect_stats(struct trie *t)
-{
-       struct node *n;
-       struct trie_stat *s = trie_stat_new();
-       int cindex = 0;
-       int pend = 0;
-       int depth = 0;
+       max = MAX_CHILDS-1;
+       while (max >= 0 && stat->nodesizes[max] == 0)
+               max--;
 
-       if (!s)
-               return NULL;
+       pointers = 0;
+       for (i = 1; i <= max; i++)
+               if (stat->nodesizes[i] != 0) {
+                       seq_printf(seq, "  %d: %d",  i, stat->nodesizes[i]);
+                       pointers += (1<<i) * stat->nodesizes[i];
+               }
+       seq_putc(seq, '\n');
+       seq_printf(seq, "\tPointers: %d\n", pointers);
 
-       rcu_read_lock();
-       n = rcu_dereference(t->trie);
+       bytes += sizeof(struct node *) * pointers;
+       seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
+       seq_printf(seq, "Total size: %d  kB\n", (bytes + 1023) / 1024);
 
-       if (!n)
-               return s;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+       seq_printf(seq, "Counters:\n---------\n");
+       seq_printf(seq,"gets = %d\n", t->stats.gets);
+       seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);
+       seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
+       seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
+       seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
+       seq_printf(seq,"skipped node resize = %d\n", t->stats.resize_node_skipped);
+#ifdef CLEAR_STATS
+       memset(&(t->stats), 0, sizeof(t->stats));
+#endif
+#endif /*  CONFIG_IP_FIB_TRIE_STATS */
+}
 
-       if (IS_TNODE(n)) {
-               struct tnode *tn = (struct tnode *)n;
-               pend = tn->pos+tn->bits;
-               s->nodesizes[tn->bits]++;
-               depth++;
-
-               while (tn && cindex < (1 << tn->bits)) {
-                       struct node *ch = rcu_dereference(tn->child[cindex]);
-                       if (ch) {
-
-                               /* Got a child */
-
-                               if (IS_LEAF(tn->child[cindex])) {
-                                       cindex++;
-
-                                       /* stats */
-                                       if (depth > s->maxdepth)
-                                               s->maxdepth = depth;
-                                       s->totdepth += depth;
-                                       s->leaves++;
-                               } else {
-                                       /*
-                                        * New tnode. Decend one level
-                                        */
-
-                                       s->tnodes++;
-                                       s->nodesizes[tn->bits]++;
-                                       depth++;
-
-                                       n = ch;
-                                       tn = (struct tnode *)n;
-                                       pend = tn->pos+tn->bits;
-
-                                       cindex = 0;
-                               }
-                       } else {
-                               cindex++;
-                               s->nullpointers++;
-                       }
+static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+{
+       struct trie_stat *stat;
 
-                       /*
-                        * Test if we are done
-                        */
+       stat = kmalloc(sizeof(*stat), GFP_KERNEL);
+       if (!stat)
+               return -ENOMEM;
 
-                       while (cindex >= (1 << tn->bits)) {
-                               /*
-                                * Move upwards and test for root
-                                * pop off all traversed  nodes
-                                */
+       seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
+                  sizeof(struct leaf), sizeof(struct tnode));
 
-                               if (NODE_PARENT(tn) == NULL) {
-                                       tn = NULL;
-                                       n = NULL;
-                                       break;
-                               }
+       if (trie_local) {
+               seq_printf(seq, "Local:\n");
+               trie_collect_stats(trie_local, stat);
+               trie_show_stats(seq, stat);
+       }
 
-                               cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
-                               tn = NODE_PARENT(tn);
-                               cindex++;
-                               n = (struct node *)tn;
-                               pend = tn->pos+tn->bits;
-                               depth--;
-                       }
-               }
+       if (trie_main) {
+               seq_printf(seq, "Main:\n");
+               trie_collect_stats(trie_main, stat);
+               trie_show_stats(seq, stat);
        }
+       kfree(stat);
 
-       rcu_read_unlock();
-       return s;
+       return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-
-static struct fib_alias *fib_triestat_get_first(struct seq_file *seq)
+static int fib_triestat_seq_open(struct inode *inode, struct file *file)
 {
-       return NULL;
+       return single_open(file, fib_triestat_seq_show, NULL);
 }
 
-static struct fib_alias *fib_triestat_get_next(struct seq_file *seq)
+static struct file_operations fib_triestat_fops = {
+       .owner  = THIS_MODULE,
+       .open   = fib_triestat_seq_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static struct node *fib_trie_get_idx(struct fib_trie_iter *iter,
+                                     loff_t pos)
 {
+       loff_t idx = 0;
+       struct node *n;
+
+       for (n = fib_trie_get_first(iter, trie_local);
+            n; ++idx, n = fib_trie_get_next(iter)) {
+               if (pos == idx)
+                       return n;
+       }
+
+       for (n = fib_trie_get_first(iter, trie_main);
+            n; ++idx, n = fib_trie_get_next(iter)) {
+               if (pos == idx)
+                       return n;
+       }
        return NULL;
 }
 
-static void *fib_triestat_seq_start(struct seq_file *seq, loff_t *pos)
+static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       if (!ip_fib_main_table)
-               return NULL;
-
-       if (*pos)
-               return fib_triestat_get_next(seq);
-       else
+       rcu_read_lock();
+       if (*pos == 0)
                return SEQ_START_TOKEN;
+       return fib_trie_get_idx(seq->private, *pos - 1);
 }
 
-static void *fib_triestat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+       struct fib_trie_iter *iter = seq->private;
+       void *l = v;
+
        ++*pos;
        if (v == SEQ_START_TOKEN)
-               return fib_triestat_get_first(seq);
-       else
-               return fib_triestat_get_next(seq);
-}
+               return fib_trie_get_idx(iter, 0);
 
-static void fib_triestat_seq_stop(struct seq_file *seq, void *v)
-{
+       v = fib_trie_get_next(iter);
+       BUG_ON(v == l);
+       if (v)
+               return v;
 
-}
+       /* continue scan in next trie */
+       if (iter->trie == trie_local)
+               return fib_trie_get_first(iter, trie_main);
 
-/*
- *     This outputs /proc/net/fib_triestats
- *
- *     It always works in backward compatibility mode.
- *     The format of the file is not supposed to be changed.
- */
+       return NULL;
+}
 
-static void collect_and_show(struct trie *t, struct seq_file *seq)
+static void fib_trie_seq_stop(struct seq_file *seq, void *v)
 {
-       int bytes = 0; /* How many bytes are used, a ref is 4 bytes */
-       int i, max, pointers;
-       struct trie_stat *stat;
-       int avdepth;
-
-       stat = trie_collect_stats(t);
-
-       bytes = 0;
-       seq_printf(seq, "trie=%p\n", t);
-
-       if (stat) {
-               if (stat->leaves)
-                       avdepth = stat->totdepth*100 / stat->leaves;
-               else
-                       avdepth = 0;
-               seq_printf(seq, "Aver depth: %d.%02d\n", avdepth / 100, avdepth % 100);
-               seq_printf(seq, "Max depth: %4d\n", stat->maxdepth);
+       rcu_read_unlock();
+}
 
-               seq_printf(seq, "Leaves: %d\n", stat->leaves);
-               bytes += sizeof(struct leaf) * stat->leaves;
-               seq_printf(seq, "Internal nodes: %d\n", stat->tnodes);
-               bytes += sizeof(struct tnode) * stat->tnodes;
+static void seq_indent(struct seq_file *seq, int n)
+{
+       while (n-- > 0) seq_puts(seq, "   ");
+}
 
-               max = MAX_CHILDS-1;
+static inline const char *rtn_scope(enum rt_scope_t s)
+{
+       static char buf[32];
 
-               while (max >= 0 && stat->nodesizes[max] == 0)
-                       max--;
-               pointers = 0;
+       switch(s) {
+       case RT_SCOPE_UNIVERSE: return "universe";
+       case RT_SCOPE_SITE:     return "site";
+       case RT_SCOPE_LINK:     return "link";
+       case RT_SCOPE_HOST:     return "host";
+       case RT_SCOPE_NOWHERE:  return "nowhere";
+       default:
+               snprintf(buf, sizeof(buf), "scope=%d", s);
+               return buf;
+       }
+}
 
-               for (i = 1; i <= max; i++)
-                       if (stat->nodesizes[i] != 0) {
-                               seq_printf(seq, "  %d: %d",  i, stat->nodesizes[i]);
-                               pointers += (1<<i) * stat->nodesizes[i];
-                       }
-               seq_printf(seq, "\n");
-               seq_printf(seq, "Pointers: %d\n", pointers);
-               bytes += sizeof(struct node *) * pointers;
-               seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
-               seq_printf(seq, "Total size: %d  kB\n", bytes / 1024);
+static const char *rtn_type_names[__RTN_MAX] = {
+       [RTN_UNSPEC] = "UNSPEC",
+       [RTN_UNICAST] = "UNICAST",
+       [RTN_LOCAL] = "LOCAL",
+       [RTN_BROADCAST] = "BROADCAST",
+       [RTN_ANYCAST] = "ANYCAST",
+       [RTN_MULTICAST] = "MULTICAST",
+       [RTN_BLACKHOLE] = "BLACKHOLE",
+       [RTN_UNREACHABLE] = "UNREACHABLE",
+       [RTN_PROHIBIT] = "PROHIBIT",
+       [RTN_THROW] = "THROW",
+       [RTN_NAT] = "NAT",
+       [RTN_XRESOLVE] = "XRESOLVE",
+};
 
-               kfree(stat);
-       }
+static inline const char *rtn_type(unsigned t)
+{
+       static char buf[32];
 
-#ifdef CONFIG_IP_FIB_TRIE_STATS
-       seq_printf(seq, "Counters:\n---------\n");
-       seq_printf(seq,"gets = %d\n", t->stats.gets);
-       seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);
-       seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
-       seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
-       seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
-       seq_printf(seq,"skipped node resize = %d\n", t->stats.resize_node_skipped);
-#ifdef CLEAR_STATS
-       memset(&(t->stats), 0, sizeof(t->stats));
-#endif
-#endif /*  CONFIG_IP_FIB_TRIE_STATS */
+       if (t < __RTN_MAX && rtn_type_names[t])
+               return rtn_type_names[t];
+       snprintf(buf, sizeof(buf), "type %d", t);
+       return buf;
 }
 
-static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+/* Pretty print the trie */
+static int fib_trie_seq_show(struct seq_file *seq, void *v)
 {
-       char bf[128];
+       const struct fib_trie_iter *iter = seq->private;
+       struct node *n = v;
 
-       if (v == SEQ_START_TOKEN) {
-               seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
-                          sizeof(struct leaf), sizeof(struct tnode));
-               if (trie_local)
-                       collect_and_show(trie_local, seq);
+       if (v == SEQ_START_TOKEN)
+               return 0;
 
-               if (trie_main)
-                       collect_and_show(trie_main, seq);
-       } else {
-               snprintf(bf, sizeof(bf), "*\t%08X\t%08X", 200, 400);
+       if (IS_TNODE(n)) {
+               struct tnode *tn = (struct tnode *) n;
+               t_key prf = ntohl(MASK_PFX(tn->key, tn->pos));
 
-               seq_printf(seq, "%-127s\n", bf);
+               if (!NODE_PARENT(n)) {
+                       if (iter->trie == trie_local)
+                               seq_puts(seq, "<local>:\n");
+                       else
+                               seq_puts(seq, "<main>:\n");
+               } else {
+                       seq_indent(seq, iter->depth-1);
+                       seq_printf(seq, "  +-- %d.%d.%d.%d/%d\n",
+                                  NIPQUAD(prf), tn->pos);
+               }
+       } else {
+               struct leaf *l = (struct leaf *) n;
+               int i;
+               u32 val = ntohl(l->key);
+
+               seq_indent(seq, iter->depth);
+               seq_printf(seq, "  |-- %d.%d.%d.%d\n", NIPQUAD(val));
+               for (i = 32; i >= 0; i--) {
+                       struct leaf_info *li = find_leaf_info(&l->list, i);
+                       if (li) {
+                               struct fib_alias *fa;
+                               list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+                                       seq_indent(seq, iter->depth+1);
+                                       seq_printf(seq, "  /%d %s %s", i,
+                                                  rtn_scope(fa->fa_scope),
+                                                  rtn_type(fa->fa_type));
+                                       if (fa->fa_tos)
+                                               seq_printf(seq, "tos =%d\n",
+                                                          fa->fa_tos);
+                                       seq_putc(seq, '\n');
+                               }
+                       }
+               }
        }
+
        return 0;
 }
 
-static struct seq_operations fib_triestat_seq_ops = {
-       .start = fib_triestat_seq_start,
-       .next  = fib_triestat_seq_next,
-       .stop  = fib_triestat_seq_stop,
-       .show  = fib_triestat_seq_show,
+static struct seq_operations fib_trie_seq_ops = {
+       .start  = fib_trie_seq_start,
+       .next   = fib_trie_seq_next,
+       .stop   = fib_trie_seq_stop,
+       .show   = fib_trie_seq_show,
 };
 
-static int fib_triestat_seq_open(struct inode *inode, struct file *file)
+static int fib_trie_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
+       struct fib_trie_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
 
-       rc = seq_open(file, &fib_triestat_seq_ops);
+       if (!s)
+               goto out;
+
+       rc = seq_open(file, &fib_trie_seq_ops);
        if (rc)
                goto out_kfree;
 
-       seq = file->private_data;
+       seq          = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
 out:
        return rc;
 out_kfree:
+       kfree(s);
        goto out;
 }
 
-static struct file_operations fib_triestat_seq_fops = {
-       .owner  = THIS_MODULE,
-       .open   = fib_triestat_seq_open,
-       .read   = seq_read,
-       .llseek = seq_lseek,
+static struct file_operations fib_trie_fops = {
+       .owner  = THIS_MODULE,
+       .open   = fib_trie_seq_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
        .release = seq_release_private,
 };
 
-int __init fib_stat_proc_init(void)
-{
-       if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_seq_fops))
-               return -ENOMEM;
-       return 0;
-}
-
-void __init fib_stat_proc_exit(void)
+static unsigned fib_flag_trans(int type, u32 mask, const struct fib_info *fi)
 {
-       proc_net_remove("fib_triestat");
-}
+       static unsigned type2flags[RTN_MAX + 1] = {
+               [7] = RTF_REJECT, [8] = RTF_REJECT,
+       };
+       unsigned flags = type2flags[type];
 
-static struct fib_alias *fib_trie_get_first(struct seq_file *seq)
-{
-       return NULL;
+       if (fi && fi->fib_nh->nh_gw)
+               flags |= RTF_GATEWAY;
+       if (mask == 0xFFFFFFFF)
+               flags |= RTF_HOST;
+       flags |= RTF_UP;
+       return flags;
 }
 
-static struct fib_alias *fib_trie_get_next(struct seq_file *seq)
+/*
+ *     This outputs /proc/net/route.
+ *     The format of the file is not supposed to be changed
+ *     and needs to be same as fib_hash output to avoid breaking
+ *     legacy utilities
+ */
+static int fib_route_seq_show(struct seq_file *seq, void *v)
 {
-       return NULL;
-}
+       struct leaf *l = v;
+       int i;
+       char bf[128];
 
-static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       if (!ip_fib_main_table)
-               return NULL;
+       if (v == SEQ_START_TOKEN) {
+               seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
+                          "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
+                          "\tWindow\tIRTT");
+               return 0;
+       }
 
-       if (*pos)
-               return fib_trie_get_next(seq);
-       else
-               return SEQ_START_TOKEN;
-}
+       if (IS_TNODE(l))
+               return 0;
 
-static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       ++*pos;
-       if (v == SEQ_START_TOKEN)
-               return fib_trie_get_first(seq);
-       else
-               return fib_trie_get_next(seq);
+       for (i=32; i>=0; i--) {
+               struct leaf_info *li = find_leaf_info(&l->list, i);
+               struct fib_alias *fa;
+               u32 mask, prefix;
 
-}
+               if (!li)
+                       continue;
 
-static void fib_trie_seq_stop(struct seq_file *seq, void *v)
-{
-}
+               mask = inet_make_mask(li->plen);
+               prefix = htonl(l->key);
 
-/*
- *     This outputs /proc/net/fib_trie.
- *
- *     It always works in backward compatibility mode.
- *     The format of the file is not supposed to be changed.
- */
+               list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+                       const struct fib_info *fi = rcu_dereference(fa->fa_info);
+                       unsigned flags = fib_flag_trans(fa->fa_type, mask, fi);
 
-static int fib_trie_seq_show(struct seq_file *seq, void *v)
-{
-       char bf[128];
+                       if (fa->fa_type == RTN_BROADCAST
+                           || fa->fa_type == RTN_MULTICAST)
+                               continue;
 
-       if (v == SEQ_START_TOKEN) {
-               if (trie_local)
-                       trie_dump_seq(seq, trie_local);
+                       if (fi)
+                               snprintf(bf, sizeof(bf),
+                                        "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+                                        fi->fib_dev ? fi->fib_dev->name : "*",
+                                        prefix,
+                                        fi->fib_nh->nh_gw, flags, 0, 0,
+                                        fi->fib_priority,
+                                        mask,
+                                        (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
+                                        fi->fib_window,
+                                        fi->fib_rtt >> 3);
+                       else
+                               snprintf(bf, sizeof(bf),
+                                        "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
+                                        prefix, 0, flags, 0, 0, 0,
+                                        mask, 0, 0, 0);
 
-               if (trie_main)
-                       trie_dump_seq(seq, trie_main);
-       } else {
-               snprintf(bf, sizeof(bf),
-                        "*\t%08X\t%08X", 200, 400);
-               seq_printf(seq, "%-127s\n", bf);
+                       seq_printf(seq, "%-127s\n", bf);
+               }
        }
 
        return 0;
 }
 
-static struct seq_operations fib_trie_seq_ops = {
-       .start = fib_trie_seq_start,
-       .next  = fib_trie_seq_next,
-       .stop  = fib_trie_seq_stop,
-       .show  = fib_trie_seq_show,
+static struct seq_operations fib_route_seq_ops = {
+       .start  = fib_trie_seq_start,
+       .next   = fib_trie_seq_next,
+       .stop   = fib_trie_seq_stop,
+       .show   = fib_route_seq_show,
 };
 
-static int fib_trie_seq_open(struct inode *inode, struct file *file)
+static int fib_route_seq_open(struct inode *inode, struct file *file)
 {
        struct seq_file *seq;
        int rc = -ENOMEM;
+       struct fib_trie_iter *s = kmalloc(sizeof(*s), GFP_KERNEL);
 
-       rc = seq_open(file, &fib_trie_seq_ops);
+       if (!s)
+               goto out;
+
+       rc = seq_open(file, &fib_route_seq_ops);
        if (rc)
                goto out_kfree;
 
-       seq = file->private_data;
+       seq          = file->private_data;
+       seq->private = s;
+       memset(s, 0, sizeof(*s));
 out:
        return rc;
 out_kfree:
+       kfree(s);
        goto out;
 }
 
-static struct file_operations fib_trie_seq_fops = {
-       .owner  = THIS_MODULE,
-       .open   = fib_trie_seq_open,
-       .read   = seq_read,
-       .llseek = seq_lseek,
-       .release= seq_release_private,
+static struct file_operations fib_route_fops = {
+       .owner  = THIS_MODULE,
+       .open   = fib_route_seq_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release_private,
 };
 
 int __init fib_proc_init(void)
 {
-       if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_seq_fops))
-               return -ENOMEM;
+       if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_fops))
+               goto out1;
+
+       if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_fops))
+               goto out2;
+
+       if (!proc_net_fops_create("route", S_IRUGO, &fib_route_fops))
+               goto out3;
+
        return 0;
+
+out3:
+       proc_net_remove("fib_triestat");
+out2:
+       proc_net_remove("fib_trie");
+out1:
+       return -ENOMEM;
 }
 
 void __init fib_proc_exit(void)
 {
        proc_net_remove("fib_trie");
+       proc_net_remove("fib_triestat");
+       proc_net_remove("route");
 }
 
 #endif /* CONFIG_PROC_FS */
index f84ba9c96551e015882d9895ac197814c3b769f1..2fc3fd38924f21844bd82841148db79fa491e884 100644 (file)
@@ -100,8 +100,7 @@ DEFINE_SPINLOCK(inet_peer_unused_lock);
 #define PEER_MAX_CLEANUP_WORK 30
 
 static void peer_check_expire(unsigned long dummy);
-static struct timer_list peer_periodic_timer =
-       TIMER_INITIALIZER(peer_check_expire, 0, 0);
+static DEFINE_TIMER(peer_periodic_timer, peer_check_expire, 0, 0);
 
 /* Exported for sysctl_net_ipv4.  */
 int inet_peer_gc_mintime = 10 * HZ,
index c1889f88262b4867bc844322351e4909f14ed434..0cee2862ed85f46d3fbbbe96c908c16aeb92489d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/file.h>
+#include <linux/rcupdate.h>
 #include <net/sock.h>
 
 #include <linux/netfilter_ipv4/ipt_owner.h>
index 15e1134da1b2af9e8aba4e110078455d4739894a..c10e4435e3b1258a9ca0b5615be8af6d103142a2 100644 (file)
@@ -485,11 +485,6 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
        TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
        buff->tstamp = skb->tstamp;
 
-       if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
-               tp->lost_out -= tcp_skb_pcount(skb);
-               tp->left_out -= tcp_skb_pcount(skb);
-       }
-
        old_factor = tcp_skb_pcount(skb);
 
        /* Fix up tso_factor for both original and new SKB.  */
index 6d6fb74f3b5291bc2639b250f284905c048de30a..2fea3f4402a0e5b0b3c7d2d8703aa6432f1e8dec 100644 (file)
@@ -123,8 +123,7 @@ DEFINE_RWLOCK(addrconf_lock);
 
 static void addrconf_verify(unsigned long);
 
-static struct timer_list addr_chk_timer =
-                       TIMER_INITIALIZER(addrconf_verify, 0, 0);
+static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0);
 static DEFINE_SPINLOCK(addrconf_verify_lock);
 
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp);
index 47122728212ab570b5eef20d45117bd33419fbc0..922549581abc266100d6a3a28676665dd509f858 100644 (file)
@@ -406,8 +406,7 @@ ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
 
        memcpy(opt->srcrt, hdr, sizeof(*hdr));
        irthdr = (struct rt0_hdr*)opt->srcrt;
-       /* Obsolete field, MBZ, when originated by us */
-       irthdr->bitmap = 0;
+       irthdr->reserved = 0;
        opt->srcrt->segments_left = n;
        for (i=0; i<n; i++)
                memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
index 16af874c9e8f15e39242b034ae59d8e623ed3e37..4fcc5a7acf6e446ce2715df397d37d78b3b34354 100644 (file)
@@ -92,7 +92,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
 
 static __u32 rt_sernum;
 
-static struct timer_list ip6_fib_timer = TIMER_INITIALIZER(fib6_run_gc, 0, 0);
+static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0);
 
 struct fib6_walker_t fib6_walker_list = {
        .prev   = &fib6_walker_list,
index a7db762de14a989049f9a817a16730bd1e1f02b9..f841bde30c18493a94fd5d522b84724a8eb82a4a 100644 (file)
@@ -50,7 +50,7 @@ static atomic_t fl_size = ATOMIC_INIT(0);
 static struct ip6_flowlabel *fl_ht[FL_HASH_MASK+1];
 
 static void ip6_fl_gc(unsigned long dummy);
-static struct timer_list ip6_fl_gc_timer = TIMER_INITIALIZER(ip6_fl_gc, 0, 0);
+static DEFINE_TIMER(ip6_fl_gc_timer, ip6_fl_gc, 0, 0);
 
 /* FL hash table lock: it protects only of GC */
 
index 9b91decbfddba43f44f05ab1fe104e9c4c016000..4de4cdad4b7d281522aeb34ca813f9db5c4fa7c0 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/file.h>
+#include <linux/rcupdate.h>
 #include <net/sock.h>
 
 #include <linux/netfilter_ipv6/ip6t_owner.h>
index a9526b773d284d1e9fca90aa719ddd26d2c22866..2bb670037df3a9de75bf1b7580d6e015aece6927 100644 (file)
@@ -161,8 +161,8 @@ match(const struct sk_buff *skb,
                            ((rtinfo->hdrlen == hdrlen) ^
                            !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
        DEBUGP("res %02X %02X %02X ", 
-                       (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->bitmap,
-                       !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->bitmap)));
+                       (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->reserved,
+                       !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->reserved)));
 
        ret = (rh != NULL)
                        &&
@@ -179,12 +179,12 @@ match(const struct sk_buff *skb,
                            !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
 
        if (ret && (rtinfo->flags & IP6T_RT_RES)) {
-               u_int32_t *bp, _bitmap;
-               bp = skb_header_pointer(skb,
-                                       ptr + offsetof(struct rt0_hdr, bitmap),
-                                       sizeof(_bitmap), &_bitmap);
+               u_int32_t *rp, _reserved;
+               rp = skb_header_pointer(skb,
+                                       ptr + offsetof(struct rt0_hdr, reserved),
+                                       sizeof(_reserved), &_reserved);
 
-               ret = (*bp == 0);
+               ret = (*rp == 0);
        }
 
        DEBUGP("#%d ",rtinfo->addrnr);
index 165b2abce1108b1b06b348e9e4cd87dde7466731..e856ae1b360a1e805097f9b409a19b3fb34dd3ca 100644 (file)
@@ -17,7 +17,7 @@
 static void nr_loopback_timer(unsigned long);
 
 static struct sk_buff_head loopback_queue;
-static struct timer_list loopback_timer = TIMER_INITIALIZER(nr_loopback_timer, 0, 0);
+static DEFINE_TIMER(loopback_timer, nr_loopback_timer, 0, 0);
 
 void __init nr_loopback_init(void)
 {
index 737681cb9a928d65800a7e85661b034764683840..31570b9a6e9aa72cca60d1953c14e47938547ebe 100644 (file)
@@ -1194,7 +1194,7 @@ EXPORT_SYMBOL(psched_time_base);
  * with 32-bit get_cycles(). Safe up to 4GHz CPU.
  */
 static void psched_tick(unsigned long);
-static struct timer_list psched_timer = TIMER_INITIALIZER(psched_tick, 0, 0);
+static DEFINE_TIMER(psched_timer, psched_tick, 0, 0);
 
 static void psched_tick(unsigned long dummy)
 {
index 9087273abf91665e078ea43884cbea00d8e3ea07..db3c708e546b81cfac87bd206998d87848252a70 100644 (file)
@@ -49,6 +49,9 @@ build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 cmd = @$(if $($(quiet)cmd_$(1)),\
       echo '  $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
 
+# Add $(obj)/ for paths that is not absolute
+objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
+
 ###
 # if_changed      - execute command if any prerequisite is newer than 
 #                   target, or command line has changed
index f04f6273685161dc45c98e11f8d1065660ca0a0f..c2d54148a91f403eb74b8b81f53a117d7100ef70 100644 (file)
@@ -91,12 +91,7 @@ foreach $object (keys(%object)) {
                     $from !~ /\.exit\.data$/ &&
                     $from !~ /\.altinstructions$/ &&
                     $from !~ /\.pdr$/ &&
-                    $from !~ /\.debug_info$/ &&
-                    $from !~ /\.debug_aranges$/ &&
-                    $from !~ /\.debug_ranges$/ &&
-                    $from !~ /\.debug_line$/ &&
-                    $from !~ /\.debug_frame$/ &&
-                    $from !~ /\.debug_loc$/ &&
+                    $from !~ /\.debug_.*$/ &&
                     $from !~ /\.exitcall\.exit$/ &&
                     $from !~ /\.eh_frame$/ &&
                     $from !~ /\.stab$/)) {
index 6ff887586479546054956d17a2a5e5faba3dce85..9623a61dfc763df8511c6d515aac2705454ce64c 100644 (file)
@@ -258,16 +258,16 @@ static void dummy_inode_free_security (struct inode *inode)
        return;
 }
 
-static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
-                              int mask)
+static int dummy_inode_init_security (struct inode *inode, struct inode *dir,
+                                     char **name, void **value, size_t *len)
 {
-       return 0;
+       return -EOPNOTSUPP;
 }
 
-static void dummy_inode_post_create (struct inode *inode, struct dentry *dentry,
-                                    int mask)
+static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
+                              int mask)
 {
-       return;
+       return 0;
 }
 
 static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
@@ -276,13 +276,6 @@ static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
        return 0;
 }
 
-static void dummy_inode_post_link (struct dentry *old_dentry,
-                                  struct inode *inode,
-                                  struct dentry *new_dentry)
-{
-       return;
-}
-
 static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry)
 {
        return 0;
@@ -294,24 +287,12 @@ static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
        return 0;
 }
 
-static void dummy_inode_post_symlink (struct inode *inode,
-                                     struct dentry *dentry, const char *name)
-{
-       return;
-}
-
 static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
                              int mask)
 {
        return 0;
 }
 
-static void dummy_inode_post_mkdir (struct inode *inode, struct dentry *dentry,
-                                   int mask)
-{
-       return;
-}
-
 static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry)
 {
        return 0;
@@ -323,12 +304,6 @@ static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
        return 0;
 }
 
-static void dummy_inode_post_mknod (struct inode *inode, struct dentry *dentry,
-                                   int mode, dev_t dev)
-{
-       return;
-}
-
 static int dummy_inode_rename (struct inode *old_inode,
                               struct dentry *old_dentry,
                               struct inode *new_inode,
@@ -337,14 +312,6 @@ static int dummy_inode_rename (struct inode *old_inode,
        return 0;
 }
 
-static void dummy_inode_post_rename (struct inode *old_inode,
-                                    struct dentry *old_dentry,
-                                    struct inode *new_inode,
-                                    struct dentry *new_dentry)
-{
-       return;
-}
-
 static int dummy_inode_readlink (struct dentry *dentry)
 {
        return 0;
@@ -886,20 +853,15 @@ void security_fixup_ops (struct security_operations *ops)
        set_to_dummy_if_null(ops, sb_post_pivotroot);
        set_to_dummy_if_null(ops, inode_alloc_security);
        set_to_dummy_if_null(ops, inode_free_security);
+       set_to_dummy_if_null(ops, inode_init_security);
        set_to_dummy_if_null(ops, inode_create);
-       set_to_dummy_if_null(ops, inode_post_create);
        set_to_dummy_if_null(ops, inode_link);
-       set_to_dummy_if_null(ops, inode_post_link);
        set_to_dummy_if_null(ops, inode_unlink);
        set_to_dummy_if_null(ops, inode_symlink);
-       set_to_dummy_if_null(ops, inode_post_symlink);
        set_to_dummy_if_null(ops, inode_mkdir);
-       set_to_dummy_if_null(ops, inode_post_mkdir);
        set_to_dummy_if_null(ops, inode_rmdir);
        set_to_dummy_if_null(ops, inode_mknod);
-       set_to_dummy_if_null(ops, inode_post_mknod);
        set_to_dummy_if_null(ops, inode_rename);
-       set_to_dummy_if_null(ops, inode_post_rename);
        set_to_dummy_if_null(ops, inode_readlink);
        set_to_dummy_if_null(ops, inode_follow_link);
        set_to_dummy_if_null(ops, inode_permission);
index 8641f8894b4c0aa458238ca8c9195a0495c9238d..f40c8221ec1ba215b9526d74993ad5e8a4ed4256 100644 (file)
@@ -1265,85 +1265,6 @@ static int inode_security_set_sid(struct inode *inode, u32 sid)
        return 0;
 }
 
-/* Set the security attributes on a newly created file. */
-static int post_create(struct inode *dir,
-                      struct dentry *dentry)
-{
-
-       struct task_security_struct *tsec;
-       struct inode *inode;
-       struct inode_security_struct *dsec;
-       struct superblock_security_struct *sbsec;
-       u32 newsid;
-       char *context;
-       unsigned int len;
-       int rc;
-
-       tsec = current->security;
-       dsec = dir->i_security;
-       sbsec = dir->i_sb->s_security;
-
-       inode = dentry->d_inode;
-       if (!inode) {
-               /* Some file system types (e.g. NFS) may not instantiate
-                  a dentry for all create operations (e.g. symlink),
-                  so we have to check to see if the inode is non-NULL. */
-               printk(KERN_WARNING "post_create:  no inode, dir (dev=%s, "
-                      "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino);
-               return 0;
-       }
-
-       if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
-               newsid = tsec->create_sid;
-       } else {
-               rc = security_transition_sid(tsec->sid, dsec->sid,
-                                            inode_mode_to_security_class(inode->i_mode),
-                                            &newsid);
-               if (rc) {
-                       printk(KERN_WARNING "post_create:  "
-                              "security_transition_sid failed, rc=%d (dev=%s "
-                              "ino=%ld)\n",
-                              -rc, inode->i_sb->s_id, inode->i_ino);
-                       return rc;
-               }
-       }
-
-       rc = inode_security_set_sid(inode, newsid);
-       if (rc) {
-               printk(KERN_WARNING "post_create:  inode_security_set_sid "
-                      "failed, rc=%d (dev=%s ino=%ld)\n",
-                      -rc, inode->i_sb->s_id, inode->i_ino);
-               return rc;
-       }
-
-       if (sbsec->behavior == SECURITY_FS_USE_XATTR &&
-           inode->i_op->setxattr) {
-               /* Use extended attributes. */
-               rc = security_sid_to_context(newsid, &context, &len);
-               if (rc) {
-                       printk(KERN_WARNING "post_create:  sid_to_context "
-                              "failed, rc=%d (dev=%s ino=%ld)\n",
-                              -rc, inode->i_sb->s_id, inode->i_ino);
-                       return rc;
-               }
-               down(&inode->i_sem);
-               rc = inode->i_op->setxattr(dentry,
-                                          XATTR_NAME_SELINUX,
-                                          context, len, 0);
-               up(&inode->i_sem);
-               kfree(context);
-               if (rc < 0) {
-                       printk(KERN_WARNING "post_create:  setxattr failed, "
-                              "rc=%d (dev=%s ino=%ld)\n",
-                              -rc, inode->i_sb->s_id, inode->i_ino);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-
 /* Hook functions begin here. */
 
 static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
@@ -1673,6 +1594,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
        struct avc_audit_data ad;
        struct file *file, *devnull = NULL;
        struct tty_struct *tty = current->signal->tty;
+       struct fdtable *fdt;
        long j = -1;
 
        if (tty) {
@@ -1706,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files)
 
                j++;
                i = j * __NFDBITS;
-               if (i >= files->max_fds || i >= files->max_fdset)
+               fdt = files_fdtable(files);
+               if (i >= fdt->max_fds || i >= fdt->max_fdset)
                        break;
-               set = files->open_fds->fds_bits[j];
+               set = fdt->open_fds->fds_bits[j];
                if (!set)
                        continue;
                spin_unlock(&files->file_lock);
@@ -1729,7 +1652,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                                                continue;
                                        }
                                        if (devnull) {
-                                               atomic_inc(&devnull->f_count);
+                                               rcuref_inc(&devnull->f_count);
                                        } else {
                                                devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
                                                if (!devnull) {
@@ -2018,14 +1941,64 @@ static void selinux_inode_free_security(struct inode *inode)
        inode_free_security(inode);
 }
 
-static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
+                                      char **name, void **value,
+                                      size_t *len)
 {
-       return may_create(dir, dentry, SECCLASS_FILE);
+       struct task_security_struct *tsec;
+       struct inode_security_struct *dsec;
+       struct superblock_security_struct *sbsec;
+       struct inode_security_struct *isec;
+       u32 newsid, clen;
+       int rc;
+       char *namep = NULL, *context;
+
+       tsec = current->security;
+       dsec = dir->i_security;
+       sbsec = dir->i_sb->s_security;
+       isec = inode->i_security;
+
+       if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
+               newsid = tsec->create_sid;
+       } else {
+               rc = security_transition_sid(tsec->sid, dsec->sid,
+                                            inode_mode_to_security_class(inode->i_mode),
+                                            &newsid);
+               if (rc) {
+                       printk(KERN_WARNING "%s:  "
+                              "security_transition_sid failed, rc=%d (dev=%s "
+                              "ino=%ld)\n",
+                              __FUNCTION__,
+                              -rc, inode->i_sb->s_id, inode->i_ino);
+                       return rc;
+               }
+       }
+
+       inode_security_set_sid(inode, newsid);
+
+       if (name) {
+               namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL);
+               if (!namep)
+                       return -ENOMEM;
+               *name = namep;
+       }
+
+       if (value && len) {
+               rc = security_sid_to_context(newsid, &context, &clen);
+               if (rc) {
+                       kfree(namep);
+                       return rc;
+               }
+               *value = context;
+               *len = clen;
+       }
+
+       return 0;
 }
 
-static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask)
+static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
 {
-       post_create(dir, dentry);
+       return may_create(dir, dentry, SECCLASS_FILE);
 }
 
 static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
@@ -2038,11 +2011,6 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru
        return may_link(dir, old_dentry, MAY_LINK);
 }
 
-static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry)
-{
-       return;
-}
-
 static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
        int rc;
@@ -2058,21 +2026,11 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const
        return may_create(dir, dentry, SECCLASS_LNK_FILE);
 }
 
-static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name)
-{
-       post_create(dir, dentry);
-}
-
 static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
 {
        return may_create(dir, dentry, SECCLASS_DIR);
 }
 
-static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask)
-{
-       post_create(dir, dentry);
-}
-
 static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
 {
        return may_link(dir, dentry, MAY_RMDIR);
@@ -2089,23 +2047,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod
        return may_create(dir, dentry, inode_mode_to_security_class(mode));
 }
 
-static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-{
-       post_create(dir, dentry);
-}
-
 static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
                                 struct inode *new_inode, struct dentry *new_dentry)
 {
        return may_rename(old_inode, old_dentry, new_inode, new_dentry);
 }
 
-static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry,
-                                      struct inode *new_inode, struct dentry *new_dentry)
-{
-       return;
-}
-
 static int selinux_inode_readlink(struct dentry *dentry)
 {
        return dentry_has_perm(current, NULL, dentry, FILE__READ);
@@ -4298,20 +4245,15 @@ static struct security_operations selinux_ops = {
 
        .inode_alloc_security =         selinux_inode_alloc_security,
        .inode_free_security =          selinux_inode_free_security,
+       .inode_init_security =          selinux_inode_init_security,
        .inode_create =                 selinux_inode_create,
-       .inode_post_create =            selinux_inode_post_create,
        .inode_link =                   selinux_inode_link,
-       .inode_post_link =              selinux_inode_post_link,
        .inode_unlink =                 selinux_inode_unlink,
        .inode_symlink =                selinux_inode_symlink,
-       .inode_post_symlink =           selinux_inode_post_symlink,
        .inode_mkdir =                  selinux_inode_mkdir,
-       .inode_post_mkdir =             selinux_inode_post_mkdir,
        .inode_rmdir =                  selinux_inode_rmdir,
        .inode_mknod =                  selinux_inode_mknod,
-       .inode_post_mknod =             selinux_inode_post_mknod,
        .inode_rename =                 selinux_inode_rename,
-       .inode_post_rename =            selinux_inode_post_rename,
        .inode_readlink =               selinux_inode_readlink,
        .inode_follow_link =            selinux_inode_follow_link,
        .inode_permission =             selinux_inode_permission,
index b62920eead3db8cbad173905ca27dff380b3be9c..d64790bcd831ad8104ec2e50c8e05ca228424fd3 100644 (file)
@@ -42,8 +42,6 @@ MODULE_LICENSE("GPL");
 #else
 #define CSP_HDR_VALUE(a,b,c,d) ((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))
 #endif
-#define LE_SHORT(v)            le16_to_cpu(v)
-#define LE_INT(v)              le32_to_cpu(v)
 
 #define RIFF_HEADER    CSP_HDR_VALUE('R', 'I', 'F', 'F')
 #define CSP__HEADER    CSP_HDR_VALUE('C', 'S', 'P', ' ')
@@ -56,20 +54,20 @@ MODULE_LICENSE("GPL");
 /*
  * RIFF data format
  */
-typedef struct riff_header {
+struct riff_header {
        __u32 name;
        __u32 len;
-} riff_header_t;
+};
 
-typedef struct desc_header {
-       riff_header_t info;
+struct desc_header {
+       struct riff_header info;
        __u16 func_nr;
        __u16 VOC_type;
        __u16 flags_play_rec;
        __u16 flags_16bit_8bit;
        __u16 flags_stereo_mono;
        __u16 flags_rates;
-} desc_header_t;
+};
 
 /*
  * prototypes
@@ -302,9 +300,9 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
        unsigned char __user *data_end;
        unsigned short func_nr = 0;
 
-       riff_header_t file_h, item_h, code_h;
+       struct riff_header file_h, item_h, code_h;
        __u32 item_type;
-       desc_header_t funcdesc_h;
+       struct desc_header funcdesc_h;
 
        unsigned long flags;
        int err;
@@ -316,12 +314,12 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
        if (copy_from_user(&file_h, data_ptr, sizeof(file_h)))
                return -EFAULT;
        if ((file_h.name != RIFF_HEADER) ||
-           (LE_INT(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
+           (le32_to_cpu(file_h.len) >= SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE - sizeof(file_h))) {
                snd_printd("%s: Invalid RIFF header\n", __FUNCTION__);
                return -EINVAL;
        }
        data_ptr += sizeof(file_h);
-       data_end = data_ptr + LE_INT(file_h.len);
+       data_end = data_ptr + le32_to_cpu(file_h.len);
 
        if (copy_from_user(&item_type, data_ptr, sizeof(item_type)))
                return -EFAULT;
@@ -331,7 +329,7 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
        }
        data_ptr += sizeof (item_type);
 
-       for (; data_ptr < data_end; data_ptr += LE_INT(item_h.len)) {
+       for (; data_ptr < data_end; data_ptr += le32_to_cpu(item_h.len)) {
                if (copy_from_user(&item_h, data_ptr, sizeof(item_h)))
                        return -EFAULT;
                data_ptr += sizeof(item_h);
@@ -344,7 +342,7 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
                case FUNC_HEADER:
                        if (copy_from_user(&funcdesc_h, data_ptr + sizeof(item_type), sizeof(funcdesc_h)))
                                return -EFAULT;
-                       func_nr = LE_SHORT(funcdesc_h.func_nr);
+                       func_nr = le16_to_cpu(funcdesc_h.func_nr);
                        break;
                case CODE_HEADER:
                        if (func_nr != info.func_req)
@@ -370,11 +368,11 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
                                if (code_h.name != INIT_HEADER)
                                        break;
                                data_ptr += sizeof(code_h);
-                               err = snd_sb_csp_load_user(p, data_ptr, LE_INT(code_h.len),
+                               err = snd_sb_csp_load_user(p, data_ptr, le32_to_cpu(code_h.len),
                                                      SNDRV_SB_CSP_LOAD_INITBLOCK);
                                if (err)
                                        return err;
-                               data_ptr += LE_INT(code_h.len);
+                               data_ptr += le32_to_cpu(code_h.len);
                        }
                        /* main microcode block */
                        if (copy_from_user(&code_h, data_ptr, sizeof(code_h)))
@@ -386,17 +384,17 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
                        }
                        data_ptr += sizeof(code_h);
                        err = snd_sb_csp_load_user(p, data_ptr,
-                                                  LE_INT(code_h.len), 0);
+                                                  le32_to_cpu(code_h.len), 0);
                        if (err)
                                return err;
 
                        /* fill in codec header */
                        strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
                        p->func_nr = func_nr;
-                       p->mode = LE_SHORT(funcdesc_h.flags_play_rec);
-                       switch (LE_SHORT(funcdesc_h.VOC_type)) {
+                       p->mode = le16_to_cpu(funcdesc_h.flags_play_rec);
+                       switch (le16_to_cpu(funcdesc_h.VOC_type)) {
                        case 0x0001:    /* QSound decoder */
-                               if (LE_SHORT(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
+                               if (le16_to_cpu(funcdesc_h.flags_play_rec) == SNDRV_SB_CSP_MODE_DSP_WRITE) {
                                        if (snd_sb_qsound_build(p) == 0)
                                                /* set QSound flag and clear all other mode flags */
                                                p->mode = SNDRV_SB_CSP_MODE_QSOUND;
@@ -426,12 +424,12 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
                                p->mode = 0;
                                snd_printd("%s: Unsupported CSP codec type: 0x%04x\n",
                                           __FUNCTION__,
-                                          LE_SHORT(funcdesc_h.VOC_type));
+                                          le16_to_cpu(funcdesc_h.VOC_type));
                                return -EINVAL;
                        }
-                       p->acc_channels = LE_SHORT(funcdesc_h.flags_stereo_mono);
-                       p->acc_width = LE_SHORT(funcdesc_h.flags_16bit_8bit);
-                       p->acc_rates = LE_SHORT(funcdesc_h.flags_rates);
+                       p->acc_channels = le16_to_cpu(funcdesc_h.flags_stereo_mono);
+                       p->acc_width = le16_to_cpu(funcdesc_h.flags_16bit_8bit);
+                       p->acc_rates = le16_to_cpu(funcdesc_h.flags_rates);
 
                        /* Decouple CSP from IRQ and DMAREQ lines */
                        spin_lock_irqsave(&p->chip->reg_lock, flags);
index b2676fa34630ce621a04059d6482f0c493bb320a..6982556ded56fd352035cd772f53dff5959ce110 100644 (file)
@@ -50,7 +50,7 @@ static struct midi_parms parms[MAX_MIDI_DEV];
 static void midi_poll(unsigned long dummy);
 
 
-static struct timer_list poll_timer = TIMER_INITIALIZER(midi_poll, 0, 0);
+static DEFINE_TIMER(poll_timer, midi_poll, 0, 0);
 
 static volatile int open_devs;
 static DEFINE_SPINLOCK(lock);
diff --git a/sound/oss/skeleton.c b/sound/oss/skeleton.c
deleted file mode 100644 (file)
index 8fea783..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- *     PCI sound skeleton example
- *
- *     (c) 1998 Red Hat Software
- *
- *     This software may be used and distributed according to the 
- *     terms of the GNU General Public License, incorporated herein by 
- *     reference.
- *
- *     This example is designed to be built in the linux/drivers/sound
- *     directory as part of a kernel build. The example is modular only
- *     drop me a note once you have a working modular driver and want
- *     to integrate it with the main code.
- *             -- Alan <alan@redhat.com>
- *
- *     This is a first draft. Please report any errors, corrections or
- *     improvements to me.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-
-/*
- *     Define our PCI vendor ID here
- */
-#ifndef PCI_VENDOR_MYIDENT
-#define PCI_VENDOR_MYIDENT                     0x125D
-
-/*
- *     PCI identity for the card.
- */
-#define PCI_DEVICE_ID_MYIDENT_MYCARD1          0x1969
-#endif
-
-#define CARD_NAME      "ExampleWave 3D Pro Ultra ThingyWotsit"
-
-#define MAX_CARDS      8
-
-/*
- *     Each address_info object holds the information about one of
- *     our card resources. In this case the MSS emulation of our
- *     ficticious card. Its used to manage and attach things.
- */
-static struct address_info     mss_data[MAX_CARDS];
-static int                     cards;
-
-/*
- *     Install the actual card. This is an example
- */
-
-static int mycard_install(struct pci_dev *pcidev)
-{
-       int iobase;
-       int mssbase;
-       int mpubase;
-       u8 x;
-       u16 w;
-       u32 v;
-       int i;
-       int dma;
-
-       /*
-        *      Our imaginary code has its I/O on PCI address 0, a
-        *      MSS on PCI address 1 and an MPU on address 2
-        *
-        *      For the example we will only initialise the MSS
-        */
-               
-       iobase = pci_resource_start(pcidev, 0);
-       mssbase = pci_resource_start(pcidev, 1);
-       mpubase = pci_resource_start(pcidev, 2);
-       
-       /*
-        *      Reset the board
-        */
-        
-       /*
-        *      Wait for completion. udelay() waits in microseconds
-        */
-        
-       udelay(100);
-       
-       /*
-        *      Ok card ready. Begin setup proper. You might for example
-        *      load the firmware here
-        */
-       
-       dma = card_specific_magic(ioaddr);
-       
-       /*
-        *      Turn on legacy mode (example), There are also byte and
-        *      dword (32bit) PCI configuration function calls
-        */
-
-       pci_read_config_word(pcidev, 0x40, &w);
-       w&=~(1<<15);                    /* legacy decode on */
-       w|=(1<<14);                     /* Reserved write as 1 in this case */
-       w|=(1<<3)|(1<<1)|(1<<0);        /* SB on , FM on, MPU on */
-       pci_write_config_word(pcidev, 0x40, w);
-       
-       /*
-        *      Let the user know we found his toy.
-        */
-        
-       printk(KERN_INFO "Programmed "CARD_NAME" at 0x%X to legacy mode.\n",
-               iobase);
-               
-       /*
-        *      Now set it up the description of the card
-        */
-        
-       mss_data[cards].io_base = mssbase;
-       mss_data[cards].irq = pcidev->irq;
-       mss_data[cards].dma = dma;
-       
-       /*
-        *      Check there is an MSS present
-        */
-
-       if(ad1848_detect(mssbase, NULL, mss_data[cards].osp)==0)
-               return 0;
-               
-       /*
-        *      Initialize it
-        */
-        
-       mss_data[cards].slots[3] = ad1848_init("MyCard MSS 16bit", 
-                       mssbase,
-                       mss_data[cards].irq,
-                       mss_data[cards].dma,
-                       mss_data[cards].dma,
-                       0,
-                       0,
-                       THIS_MODULE);
-
-       cards++;        
-       return 1;
-}
-
-
-/*
- *     This loop walks the PCI configuration database and finds where
- *     the sound cards are.
- */
-int init_mycard(void)
-{
-       struct pci_dev *pcidev=NULL;
-       int count=0;
-               
-       while((pcidev = pci_find_device(PCI_VENDOR_MYIDENT, PCI_DEVICE_ID_MYIDENT_MYCARD1, pcidev))!=NULL)
-       {
-               if (pci_enable_device(pcidev))
-                       continue;
-               count+=mycard_install(pcidev);
-               if(count)
-                       return 0;
-               if(count==MAX_CARDS)
-                       break;
-       }
-       
-       if(count==0)
-               return -ENODEV;
-       return 0;
-}
-
-/*
- *     This function is called when the user or kernel loads the 
- *     module into memory.
- */
-
-
-int init_module(void)
-{
-       if(init_mycard()<0)
-       {
-               printk(KERN_ERR "No "CARD_NAME" cards found.\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-/*
- *     This is called when it is removed. It will only be removed 
- *     when its use count is 0.
- */
-void cleanup_module(void)
-{
-       for(i=0;i< cards; i++)
-       {
-               /*
-                *      Free attached resources
-                */
-                
-               ad1848_unload(mss_data[i].io_base,
-                             mss_data[i].irq,
-                             mss_data[i].dma,
-                             mss_data[i].dma,
-                             0);
-               /*
-                *      And disconnect the device from the kernel
-                */
-               sound_unload_audiodevice(mss_data[i].slots[3]);
-       }
-}
-
index a686be936aff42deb28519f156418762216d1132..95fa81e26de21f395c3e9a13e7fab853728df3df 100644 (file)
@@ -681,8 +681,7 @@ static void do_sequencer_timer(unsigned long dummy)
 }
 
 
-static struct timer_list seq_timer =
-               TIMER_INITIALIZER(do_sequencer_timer, 0, 0);
+static DEFINE_TIMER(seq_timer, do_sequencer_timer, 0, 0);
 
 void request_sound_timer(int count)
 {
index 6afe29b763b747e5b9b4839e35ccddb03b668b91..c9d04518b1722e95e93fc8c832a89f8df4ea084e 100644 (file)
@@ -28,8 +28,7 @@ static unsigned long prev_event_time;
 
 static void     poll_def_tmr(unsigned long dummy);
 static DEFINE_SPINLOCK(lock);
-
-static struct timer_list def_tmr = TIMER_INITIALIZER(poll_def_tmr, 0, 0);
+static DEFINE_TIMER(def_tmr, poll_def_tmr, 0, 0);
 
 static unsigned long
 tmr2ticks(int tmr_value)
index be00cf128651ef60d3e18fb3e7260ed3ede2659a..74ae75f9e2dc40e132a6b5e65a9fd68014698c30 100644 (file)
@@ -78,8 +78,7 @@ static void (*midi_input_intr) (int dev, unsigned char data);
 static void poll_uart6850(unsigned long dummy);
 
 
-static struct timer_list uart6850_timer =
-               TIMER_INITIALIZER(poll_uart6850, 0, 0);
+static DEFINE_TIMER(uart6850_timer, poll_uart6850, 0, 0);
 
 static void uart6850_input_loop(void)
 {